formidable
formidable copied to clipboard
ContentType: text/plain not showing in fields
Support plan
- Which support plan is this issue covered by? Community
- Currently blocking your project/work? yes
- Affecting a production system? yes
Context
- Node.js version: 16.13.1
- Release Line of Formidable (Legacy, Current, Next): Next
- Formidable exact version: 3.2.4
- Environment (node, browser, native, OS): node
- Used with (popular names of modules): nextjs, next-connect
What are you trying to achieve or the steps to reproduce?
Im trying to make custom server functionality on nextjs api route, where i get some request data from game as "multipart/form-data;" but some of the data has "text/plain" content type.
router.post(async (req, res) => {
const form = new IncomingForm();
form.parse(req, (err, fields, files) => {
console.log(fields);
console.log(files);
});
res.end();
});
export const config = {
api: {
bodyParser: false,
},
};
What was the result you got?
Only the files variable gets populated. As i needed to disable parser for nextjs i cant really use req.body. looping for 'text/plain' mimetype in files and parsing them manualy is not desired either
What result did you expect?
'text/plain' content type parsed into fields variable
If I understand correctly you want to access files sent as text/plain as if it was another field ?
This line in the code separates fields from files:
if (!part.mimetype) {
So if you don't have a mimetype it will appear as a field
Yes, i managed to do it in an ugly way around
for (let [fileField, filesArray] of Object.entries(files)) {
const file = (filesArray as File[])[0];
switch (fileField) {
case "id":
id = await fileToString(file.filepath);
fs.rm(file.filepath);
break;
case "extraData":
extraData = JSON.parse(await fileToString(file.filepath));
fs.rm(file.filepath);
break;
default:
tile = file;
break;
}
}
but i think as text/plain usually contain string, if they arent too big maybe they should convert to fileds also?
for disclaimer i cant really change how i receive data, and 'id','extradata' are bassically oneliners i remember that i used that API with multer some time ago and it was quite simple
Do you suggest to change formidable ?
@GrosSacASac I would like to see this change as well, I missed this issue but I commented about running into the same problem in #495
What exactly should change ?
if mimetype is text/plain it should be decoded into fields instead of file with provided charset, unless explicity specified, or allow us to exclude fields from converting to files
not automatically, and not default behavior
or allow us to exclude fields from converting to files
yep, through option.
Formidable v1 used to put "a" in fields
for:
Invoke-RestMethod -Uri '...' -Method Post -Form @{ a = 'A'; file = Get-Item -Path '.\foo.txt' }
which sends:
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name="a"
Upgrading to Formidable v2 broke my app.
NB: curl does not send "Content-Type" for non-files.
Workaround tested on v2:
form.onPart = function (part) {
if (part.mimetype && !part.headers['content-disposition']?.match(/filename="/)) {
// we want it to be a "field" (cf https://github.com/node-formidable/formidable/issues/875 )
delete part.mimetype
}
form._handlePart(part);
}
I have the same issue. My user is calling my API with a C# client. Their multipart/form implemtation always adds the text/plain
mimetype. To solve the issue, I have to apply the solution from @prigaux above.
I think this should be fixed upstream in this library, no?
That's why we even expose internals and allow overriding, so it can be extended. ;)
Converting text/plain to fields by passing some option, could be a good feature too.
Formidable v1 used to put "a" in fields for:
Really strange.. :D Never noticed that, or I forgot it.
That's weird. And what happens when multiple? Multiple a
s or what? haha.
I can confirm that there's no way to succesfully get fields
data from submited forms using HttpClient
on C#
Had no previous issues using v1
@prigaux workaround works great!
So, the code used to look at the existence of a filename and would consider it a field if a file name did not exist.
I've been tracing back the code and it used to be what I would consider correct: https://github.com/node-formidable/formidable/blob/15f174f2457684fbfb76197fced22ae0fa52e8b2/src/incoming_form.js#L195
But then was changed to look at mime type here: https://github.com/node-formidable/formidable/commit/621e72a4deac6acf5f47f84986648d908eb2ae89
I'm not really sure what the change fixed, but it's not correct. A field is a file if it contains a filename. Otherwise, it's a field. Right??
As of now only workaround by @prigaux is working, Is there any fix in library? I am using Retrofit as client in Android app.
I am using this code:
const form = formidable({
uploadDir: storagePath,
createDirsFromUploads: true,
keepExtensions: true,
});
form.onPart = function (part) {
log.info('part:', part)
if (part.mimetype && !(part as any).headers['content-disposition']?.match(/filename="/)) {
// we want it to be a "field" (cf https://github.com/node-formidable/formidable/issues/875 )
part.mimetype = null
}
form._handlePart(part);
}
After add 'onPart' function, the uploaded file can not open any more; if I comment them, the uploaded file can open again.