79 lines
1.6 KiB
JavaScript
79 lines
1.6 KiB
JavaScript
import {randomBytes} from 'crypto';
|
|
|
|
import {isBlob} from './is.js';
|
|
|
|
const carriage = '\r\n';
|
|
const dashes = '-'.repeat(2);
|
|
const carriageLength = Buffer.byteLength(carriage);
|
|
|
|
/**
|
|
* @param {string} boundary
|
|
*/
|
|
const getFooter = boundary => `${dashes}${boundary}${dashes}${carriage.repeat(2)}`;
|
|
|
|
/**
|
|
* @param {string} boundary
|
|
* @param {string} name
|
|
* @param {*} field
|
|
*
|
|
* @return {string}
|
|
*/
|
|
function getHeader(boundary, name, field) {
|
|
let header = '';
|
|
|
|
header += `${dashes}${boundary}${carriage}`;
|
|
header += `Content-Disposition: form-data; name="${name}"`;
|
|
|
|
if (isBlob(field)) {
|
|
header += `; filename="${field.name}"${carriage}`;
|
|
header += `Content-Type: ${field.type || 'application/octet-stream'}`;
|
|
}
|
|
|
|
return `${header}${carriage.repeat(2)}`;
|
|
}
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
export const getBoundary = () => randomBytes(8).toString('hex');
|
|
|
|
/**
|
|
* @param {FormData} form
|
|
* @param {string} boundary
|
|
*/
|
|
export async function * formDataIterator(form, boundary) {
|
|
for (const [name, value] of form) {
|
|
yield getHeader(boundary, name, value);
|
|
|
|
if (isBlob(value)) {
|
|
yield * value.stream();
|
|
} else {
|
|
yield value;
|
|
}
|
|
|
|
yield carriage;
|
|
}
|
|
|
|
yield getFooter(boundary);
|
|
}
|
|
|
|
/**
|
|
* @param {FormData} form
|
|
* @param {string} boundary
|
|
*/
|
|
export function getFormDataLength(form, boundary) {
|
|
let length = 0;
|
|
|
|
for (const [name, value] of form) {
|
|
length += Buffer.byteLength(getHeader(boundary, name, value));
|
|
|
|
length += isBlob(value) ? value.size : Buffer.byteLength(String(value));
|
|
|
|
length += carriageLength;
|
|
}
|
|
|
|
length += Buffer.byteLength(getFooter(boundary));
|
|
|
|
return length;
|
|
}
|