mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fix: FormData filename in content-disposition (#46543)
Summary: This Pull Request fixes a regression introduced in https://github.com/facebook/react-native/commit/7c7e9e6571c1f702213e9ffbb40921cd5a1a786b, which adds a `filename*` attribute to the `content-disposition` of a FormData part. However, as the [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#directives) states, there is no `filename*` attribute for the `content-disposition` header in case of a form data. The `filename*` attribute would break the parsing of form data in the request, such as in frameworks like `Next.js` which uses the web implementation of [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request). Fixes https://github.com/facebook/react-native/issues/44737 ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [General] [Fixed] - Remove non compliant `filename*` attribute in a FormData `content-disposition` header Pull Request resolved: https://github.com/facebook/react-native/pull/46543 Test Plan: - Clone the `react-native` repo - Create a simple JS file that will act as a node server and execute it ```javascript const http = require('http'); const server = http.createServer(async function (r, res) { const req = new Request(new URL(r.url, 'http://localhost:3000'), { headers: r.headers, method: r.method, body: r, duplex: 'half', }); const fileData = await req.formData(); console.log(fileData); res.writeHead(200); res.end(); }); server.listen(3000); ``` - Go to `packages/rn-tester` - Add a `useEffect` in `js/RNTesterAppShared.js` ```javascript React.useEffect(() => { const formData = new FormData(); formData.append('file', { uri: 'https://www.gravatar.com/avatar', name: '测试photo/1.jpg', type: 'image/jpeg', }); fetch('http://localhost:3000', { method: 'POST', body: formData, }).then(res => console.log(res.ok)); }); ``` - Run the app on iOS or Android - The node server should output the file added to the FormData with an encoded name Reviewed By: robhogan Differential Revision: D66643317 Pulled By: yungsters fbshipit-source-id: 0d531528005025bff303505363671e854c0a2b63
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b886bc4db9
commit
f791fb9e66
+11
-3
@@ -28,6 +28,15 @@ type FormDataPart =
|
||||
...
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a FormData filename compliant with RFC 2183
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#directives
|
||||
*/
|
||||
function encodeFilename(filename: string): string {
|
||||
return encodeURIComponent(filename.replace(/\//g, '_'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Polyfill for XMLHttpRequest2 FormData API, allowing multipart POST requests
|
||||
* with mixed data (string, native files) to be submitted via XMLHttpRequest.
|
||||
@@ -82,9 +91,8 @@ class FormData {
|
||||
// content type (cf. web Blob interface.)
|
||||
if (typeof value === 'object' && !Array.isArray(value) && value) {
|
||||
if (typeof value.name === 'string') {
|
||||
headers['content-disposition'] += `; filename="${
|
||||
value.name
|
||||
}"; filename*=utf-8''${encodeURI(value.name)}`;
|
||||
headers['content-disposition'] +=
|
||||
`; filename="${encodeFilename(value.name)}"`;
|
||||
}
|
||||
if (typeof value.type === 'string') {
|
||||
headers['content-type'] = value.type;
|
||||
|
||||
@@ -48,8 +48,7 @@ describe('FormData', function () {
|
||||
type: 'image/jpeg',
|
||||
name: 'photo.jpg',
|
||||
headers: {
|
||||
'content-disposition':
|
||||
'form-data; name="photo"; filename="photo.jpg"; filename*=utf-8\'\'photo.jpg',
|
||||
'content-disposition': 'form-data; name="photo"; filename="photo.jpg"',
|
||||
'content-type': 'image/jpeg',
|
||||
},
|
||||
fieldName: 'photo',
|
||||
@@ -70,7 +69,7 @@ describe('FormData', function () {
|
||||
name: '测试photo.jpg',
|
||||
headers: {
|
||||
'content-disposition':
|
||||
'form-data; name="photo"; filename="测试photo.jpg"; filename*=utf-8\'\'%E6%B5%8B%E8%AF%95photo.jpg',
|
||||
'form-data; name="photo"; filename="%E6%B5%8B%E8%AF%95photo.jpg"',
|
||||
'content-type': 'image/jpeg',
|
||||
},
|
||||
fieldName: 'photo',
|
||||
|
||||
Reference in New Issue
Block a user