您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A UMD build of parse-multipart-data
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/517244/1483543/parse-multipart-data-umd.js
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.parseMultipartData = {}));
- })(this, (function (exports) { 'use strict';
- function process(part) {
- // will transform this object:
- // { header: 'Content-Disposition: form-data; name="uploads[]"; filename="A.txt"',
- // info: 'Content-Type: text/plain',
- // part: 'AAAABBBB' }
- // into this one:
- // { filename: 'A.txt', type: 'text/plain', data: <Buffer 41 41 41 41 42 42 42 42> }
- const obj = function (str) {
- const k = str.split('=');
- const a = k[0].trim();
- const b = JSON.parse(k[1].trim());
- const o = {};
- Object.defineProperty(o, a, {
- value: b,
- writable: true,
- enumerable: true,
- configurable: true
- });
- return o;
- };
- const header = part.contentDispositionHeader.split(';');
- const filenameData = header[2];
- let input = {};
- if (filenameData) {
- input = obj(filenameData);
- const contentType = part.contentTypeHeader.split(':')[1].trim();
- Object.defineProperty(input, 'type', {
- value: contentType,
- writable: true,
- enumerable: true,
- configurable: true
- });
- }
- // always process the name field
- Object.defineProperty(input, 'name', {
- value: header[1].split('=')[1].replace(/"/g, ''),
- writable: true,
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(input, 'data', {
- value: new Uint8Array(part.part),
- writable: true,
- enumerable: true,
- configurable: true
- });
- return input;
- }
- const ParsingState = (ParsingState => {
- ParsingState[(ParsingState.INIT = 0)] = 'INIT';
- ParsingState[(ParsingState.READING_HEADERS = 1)] = 'READING_HEADERS';
- ParsingState[(ParsingState.READING_DATA = 2)] = 'READING_DATA';
- ParsingState[(ParsingState.READING_PART_SEPARATOR = 3)] = 'READING_PART_SEPARATOR';
- return ParsingState;
- })({});
- function parse(multipartBodyBuffer, boundary) {
- let lastline = '';
- let contentDispositionHeader = '';
- let contentTypeHeader = '';
- let state = ParsingState.INIT;
- let buffer = [];
- const allParts = [];
- let currentPartHeaders = [];
- for (let i = 0; i < multipartBodyBuffer.length; i++) {
- const oneByte = multipartBodyBuffer[i];
- const prevByte = i > 0 ? multipartBodyBuffer[i - 1] : null;
- // 0x0a => \n
- // 0x0d => \r
- const newLineDetected = oneByte === 0x0a && prevByte === 0x0d;
- const newLineChar = oneByte === 0x0a || oneByte === 0x0d;
- if (!newLineChar) lastline += String.fromCharCode(oneByte);
- if (ParsingState.INIT === state && newLineDetected) {
- // searching for boundary
- if ('--' + boundary === lastline) {
- state = ParsingState.READING_HEADERS; // found boundary. start reading headers
- }
- lastline = '';
- } else if (ParsingState.READING_HEADERS === state && newLineDetected) {
- // parsing headers. Headers are separated by an empty line from the content. Stop reading headers when the line is empty
- if (lastline.length) {
- currentPartHeaders.push(lastline);
- } else {
- // found empty line. search for the headers we want and set the values
- for (const h of currentPartHeaders) {
- if (h.toLowerCase().startsWith('content-disposition:')) {
- contentDispositionHeader = h;
- } else if (h.toLowerCase().startsWith('content-type:')) {
- contentTypeHeader = h;
- }
- }
- state = ParsingState.READING_DATA;
- buffer = [];
- }
- lastline = '';
- } else if (ParsingState.READING_DATA === state) {
- // parsing data
- if (lastline.length > boundary.length + 4) {
- lastline = ''; // mem save
- }
- if ('--' + boundary === lastline) {
- const j = buffer.length - lastline.length;
- const part = buffer.slice(0, j - 1);
- allParts.push(process({
- contentDispositionHeader,
- contentTypeHeader,
- part
- }));
- buffer = [];
- currentPartHeaders = [];
- lastline = '';
- state = ParsingState.READING_PART_SEPARATOR;
- contentDispositionHeader = '';
- contentTypeHeader = '';
- } else {
- buffer.push(oneByte);
- }
- if (newLineDetected) {
- lastline = '';
- }
- } else if (ParsingState.READING_PART_SEPARATOR === state) {
- if (newLineDetected) {
- state = ParsingState.READING_HEADERS;
- }
- }
- }
- return allParts;
- }
- // read the boundary from the content-type header sent by the http client
- // this value may be similar to:
- // 'multipart/form-data; boundary=----WebKitFormBoundaryvm5A9tzU1ONaGP5B',
- function getBoundary(header) {
- const items = header.split(';');
- if (items) {
- for (let i = 0; i < items.length; i++) {
- const item = new String(items[i]).trim();
- if (item.indexOf('boundary') >= 0) {
- const k = item.split('=');
- return new String(k[1]).trim().replace(/^["']|["']$/g, '');
- }
- }
- }
- return '';
- }
- exports.getBoundary = getBoundary;
- exports.parse = parse;
- }));
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址