Skip to content

Commit cf9ee6f

Browse files
edmundhungjacob-ebeybrophdawg11
authored
fix: empty filename should not be treated as string (#28)
Co-authored-by: Jacob Ebey <jacob.ebey@live.com> Co-authored-by: Matt Brophy <matt@brophy.org>
1 parent 9cabb20 commit cf9ee6f

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

.changeset/light-snails-leave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/web-fetch": patch
3+
---
4+
5+
If you create a FormData object on the browser with empty file input, a default empty file entry (i.e. new File([], '')) would be generated. However, this is currently presented as an empty string instead when you read it on the server. This should fix the discrepancy.

packages/fetch/src/utils/form-data.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,10 @@ export const toFormData = async (source) => {
104104
const form = new FormData()
105105
const parts = iterateMultipart(body, boundary)
106106
for await (const { name, data, filename, contentType } of parts) {
107-
if (filename) {
107+
if (typeof filename === 'string') {
108108
form.append(name, new File([data], filename, { type: contentType }))
109+
} else if (typeof filename !== 'undefined') {
110+
form.append(name, new File([], '', { type: contentType }))
109111
} else {
110112
form.append(name, new TextDecoder().decode(data), filename)
111113
}

packages/fetch/test/request.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,52 @@ describe('Request', () => {
439439
expect(file.lastModified).to.be.a('number');
440440
});
441441
});
442+
443+
it('should decode empty file inputs into File instances (web FormData)', async () => {
444+
const ogFormData = new WebFormData();
445+
ogFormData.append('a', 1);
446+
// This is what happens when you construct the form data set with an empty file input:
447+
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#constructing-the-form-data-set
448+
ogFormData.append('file', new File([], '', { type: 'application/octet-stream' }));
449+
const request = new Request(base, {
450+
method: 'POST',
451+
body: ogFormData,
452+
});
453+
const clonedRequest = request.clone();
454+
return clonedRequest.formData().then(async clonedFormData => {
455+
expect(clonedFormData.get('a')).to.equal("1");
456+
const file = clonedFormData.get('file');
457+
expect(file.name).to.equal("");
458+
expect(file.type).to.equal("application/octet-stream");
459+
expect(file.size).to.equal(0);
460+
});
461+
});
462+
463+
it.skip('should decode empty file inputs into File instances (node FormData)', async () => {
464+
const ogFormData = new FormData();
465+
ogFormData.append('a', 1);
466+
// This is what happens when you construct the form data set with an empty file input:
467+
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#constructing-the-form-data-set
468+
ogFormData.append('file', Buffer.from(''), {
469+
// Note: This doesn't work at the moment due to https://github.com/form-data/form-data/issues/412.
470+
// There is a v4 released which has a fix that might handle this but I
471+
// wasn't positive if it had breaking changes that would impact us so we
472+
// can handle an upgrade separately.
473+
filename: '',
474+
contentType: 'application/octet-stream',
475+
});
476+
const request = new Request(base, {
477+
method: 'POST',
478+
body: ogFormData,
479+
});
480+
const clonedRequest = request.clone();
481+
return clonedRequest.formData().then(async clonedFormData => {
482+
expect(clonedFormData.get('a')).to.equal("1");
483+
const file = clonedFormData.get('file');
484+
expect(file.name).to.equal("");
485+
expect(file.type).to.equal("application/octet-stream");
486+
expect(file.size).to.equal(0);
487+
});
488+
489+
});
442490
});

0 commit comments

Comments
 (0)