Skip to content

Commit

Permalink
Merge pull request #8 from asynch8/allow-multiple-files
Browse files Browse the repository at this point in the history
Updated codebase with functionality and tests to support multiple files being uploaded in the same form variable
  • Loading branch information
FlameWolf authored Apr 8, 2024
2 parents 74cab65 + 853f037 commit 741a9ae
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 3 deletions.
18 changes: 16 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ const formDataParser = async (instance, options) => {
const bus = busboy({ headers: message.headers, limits, defParamCharset: "utf8" });
bus.on("file", (name, stream, info) => {
results.push(storage.process(name, stream, info));
body[name] = JSON.stringify(info);
if(!body[name]) {
body[name] = JSON.stringify(info);
} else if (body[name] && !Array.isArray(body[name])) {
body[name] = [body[name], JSON.stringify(info)];
} else {
body[name].push(JSON.stringify(info));
}
});
bus.on("field", (name, value) => {
body[name] = parseField(name, value);
Expand All @@ -38,11 +44,19 @@ const formDataParser = async (instance, options) => {
const body = request.body;
const files = request.__files__;
if (files?.length) {
const newBody = {};
for (const file of files) {
const field = file.field;
delete file.field;
body[field] = file;
if (!newBody[field]) {
newBody[field] = file;
} else if (newBody[field] && !Array.isArray(newBody[field])) {
newBody[field] = [newBody[field], file];
} else {
newBody[field].push(file);
}
}
Object.assign(body, newBody);
}
delete request.__files__;
});
Expand Down
51 changes: 51 additions & 0 deletions test/multifile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use strict";

const setup = require("./setup-multifile");
const tap = require("tap");
const { Readable } = require("stream");
const { once } = require("events");
const formData = require("form-data");
const http = require("http");
const path = require("path");
const fs = require("fs");


async function sendRequest(instance) {
const form = new formData();
const req = http.request({
protocol: "http:",
hostname: "localhost",
port: instance.server.address().port,
path: "/",
headers: form.getHeaders(),
method: "POST"
});
const filePath = path.join(__dirname, "chequer.png");
form.append("file", fs.createReadStream(filePath));
form.append("files", fs.createReadStream(filePath));
form.append("files", fs.createReadStream(filePath));
form.append("files", fs.createReadStream(filePath));
return form.pipe(req);
};

tap.test("should allow multiple files in one field", async t => {
const instance = require("fastify").fastify();
t.teardown(async () => {
await instance.close();
});
try {
instance.addHook("onResponse", async (request, reply) => {
const requestBody = request.body;
t.isArray(requestBody.files);
t.ok(requestBody.files[0].stream instanceof Readable);
t.ok(requestBody.files[1].stream instanceof Readable);
t.equal(reply.statusCode, 200);
});
await setup(instance, undefined, false);
const req = await sendRequest(instance);
const [res] = await once(req, "response");
res.resume();
} catch (err) {
console.log(err);
}
});
2 changes: 1 addition & 1 deletion test/no-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ tap.test("should parse fields as strings when there is no schema", async t => {
} catch (err) {
console.log(err);
}
});
});
36 changes: 36 additions & 0 deletions test/setup-multifile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict";

const formDataParser = require("../index");

const requestSchema = {
consumes: ["multipart/form-data"],
body: {
type: "object",
properties: {
file: {
type: "string",
format: "binary"
},
files: {
type: "array",
items: {
type: "string",
format: "binary"
}
},
}
}
};
module.exports = async function (instance, options = undefined, includeSchema = true) {
instance.register(formDataParser, options);
instance.post(
"/",
{
schema: includeSchema && requestSchema
},
async (request, reply) => {
reply.status(200).send();
}
);
await instance.listen({ port: 0, host: "::" });
};

0 comments on commit 741a9ae

Please sign in to comment.