admin管理员组文章数量:1122832
I am developing a React Native (Expo) application where users can upload files with descriptions. However, I am encountering issues when trying to send the files to the server via the fetch API using FormData. The server responds with errors or fails to receive the file and description data properly.
What I Want to Achieve: Allow users to pick files (using expo-document-picker) and optionally add descriptions for each file. Send the files and their descriptions as a POST request to the server using FormData. Ensure that files are properly processed on the server and the upload succeeds. Current Code: Here’s the relevant part of my implementation:
I use DocumentPicker to select files and store them in the files state. I construct a FormData object, appending each file and its description. I send this data using the fetch API.
if (!files || files.length === 0) {
alert('No files selected. Please select at least one file to upload.');
return;
}
if (Object.keys(descriptions).length !== files.length) {
alert('Each file must have a corresponding description.');
return;
}
setLoading(true);
try {
const formData = new FormData();
files.forEach((file, index) => {
formData.append('files', {
uri: file.uri.startsWith('file://') ? file.uri : `file://${file.uri}`, // Ensure proper URI
name: file.name || `file_${index}`, // Assign name
type: file.type || 'application/octet-stream', // Default MIME type
});
formData.append('descriptions', descriptions[index] || ''); // Append descriptions
});
// Debugging FormData
console.log('FormData before sending:');
for (const pair of formData.entries()) {
console.log(pair[0], pair[1]);
}
// API Request
const response = await fetch(
`${process.env.EXPO_PUBLIC_API_URL}/v1/assets/assignments/${assignment_id}`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${user.token}`, // Add auth token only
},
body: formData, // FormData automatically includes the boundary
}
);
if (!response.ok) {
const errorText = await response.text();
console.error('Backend Response Error:', errorText);
alert(`Error from server: ${errorText}`);
return;
}
alert('Files uploaded successfully!');
navigation.goBack();
} catch (error) {
console.error('Error uploading files:', error);
alert(`Error uploading files: ${error.message}`);
} finally {
setLoading(false);
}
};
Problem:
The files are either not received by the server or the fetch API fails with an error. Sometimes, the server reports missing or corrupted file data. The FormData object doesn't appear to work as expected.
Debugging Steps Taken: Verified that the DocumentPicker is correctly returning file metadata (e.g., uri, name, type). Used console.log to confirm that FormData is being populated with the files and descriptions. Tried adding the Content-Type header manually (e.g., multipart/form-data), but it caused issues because fetch sets this header automatically for FormData.
Environment Details: Expo SDK: ~51.0.28 React Native: 0.74.5 Backend: Node.js/Express
Questions: What is the correct way to upload files using fetch and FormData in React Native (Expo)? Is there a specific issue with file URIs (e.g., file:// or base64) that I need to address? How can I ensure that the server properly receives both the file data and the descriptions?
I am developing a React Native (Expo) application where users can upload files with descriptions. However, I am encountering issues when trying to send the files to the server via the fetch API using FormData. The server responds with errors or fails to receive the file and description data properly.
What I Want to Achieve: Allow users to pick files (using expo-document-picker) and optionally add descriptions for each file. Send the files and their descriptions as a POST request to the server using FormData. Ensure that files are properly processed on the server and the upload succeeds. Current Code: Here’s the relevant part of my implementation:
I use DocumentPicker to select files and store them in the files state. I construct a FormData object, appending each file and its description. I send this data using the fetch API.
if (!files || files.length === 0) {
alert('No files selected. Please select at least one file to upload.');
return;
}
if (Object.keys(descriptions).length !== files.length) {
alert('Each file must have a corresponding description.');
return;
}
setLoading(true);
try {
const formData = new FormData();
files.forEach((file, index) => {
formData.append('files', {
uri: file.uri.startsWith('file://') ? file.uri : `file://${file.uri}`, // Ensure proper URI
name: file.name || `file_${index}`, // Assign name
type: file.type || 'application/octet-stream', // Default MIME type
});
formData.append('descriptions', descriptions[index] || ''); // Append descriptions
});
// Debugging FormData
console.log('FormData before sending:');
for (const pair of formData.entries()) {
console.log(pair[0], pair[1]);
}
// API Request
const response = await fetch(
`${process.env.EXPO_PUBLIC_API_URL}/v1/assets/assignments/${assignment_id}`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${user.token}`, // Add auth token only
},
body: formData, // FormData automatically includes the boundary
}
);
if (!response.ok) {
const errorText = await response.text();
console.error('Backend Response Error:', errorText);
alert(`Error from server: ${errorText}`);
return;
}
alert('Files uploaded successfully!');
navigation.goBack();
} catch (error) {
console.error('Error uploading files:', error);
alert(`Error uploading files: ${error.message}`);
} finally {
setLoading(false);
}
};
Problem:
The files are either not received by the server or the fetch API fails with an error. Sometimes, the server reports missing or corrupted file data. The FormData object doesn't appear to work as expected.
Debugging Steps Taken: Verified that the DocumentPicker is correctly returning file metadata (e.g., uri, name, type). Used console.log to confirm that FormData is being populated with the files and descriptions. Tried adding the Content-Type header manually (e.g., multipart/form-data), but it caused issues because fetch sets this header automatically for FormData.
Environment Details: Expo SDK: ~51.0.28 React Native: 0.74.5 Backend: Node.js/Express
Questions: What is the correct way to upload files using fetch and FormData in React Native (Expo)? Is there a specific issue with file URIs (e.g., file:// or base64) that I need to address? How can I ensure that the server properly receives both the file data and the descriptions?
Share Improve this question asked Nov 21, 2024 at 11:57 Abdella MunirAbdella Munir 11 bronze badge1 Answer
Reset to default 0From your question, you are trying to upload multiple files. First, your API must have been confirgured to process multiple entries of both the file and description keys. However, in your code, you are sending file
, instead of file[]
.
In your code, assuming you had earlier set some state variables, change your code from this:
files.forEach((file, index) => {
formData.append('files', {
uri: file.uri.startsWith('file://') ? file.uri : `file://${file.uri}`, // Ensure proper URI
name: file.name || `file_${index}`, // Assign name
type: file.type || 'application/octet-stream', // Default MIME type
});
formData.append('descriptions', descriptions[index] || ''); // Append descriptions
});
to this:
files.forEach((file, index) => {
formData.append('files[]', {
uri: file.uri,
name: file.name,
type: file.type || 'application/octet-stream', // Default MIME type
});
formData.append('descriptions[]', descriptions[index] || ''); // Append descriptions
});
To further help you debug the codes, just do a console.log(formData)
to see your data before upload. In your log, you will see something like below:
{"_parts": [["files[]", [Object]],["files[]", [Object]],["files[]", [Object]],["description[]", ["first description"]],["description[]", ["second description"]],["description[]", ["third description"]]]}
Hoping this helps.
本文标签: How to upload multiple files on React native ExpoStack Overflow
版权声明:本文标题:How to upload multiple files on React native Expo? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736311135a1934630.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论