使用Fetch与FormData上传文件:Ubuntu成功Windows 10失败求助
Hi Hearen, let's work through this tricky cross-platform file upload issue step by step!
问题根源拆解
Windows下MIME类型异常的原因
Different systems have slight differences in how browsers recognize local file MIME types. On Windows, if the system's file extension-MIME type association isn't configured correctly, or the browser can't accurately identify the file type, it will default to marking the file asapplication/octet-stream. Meanwhile, browsers on Ubuntu can correctly recognizetext/csv, which leads to inconsistent file types received by the server and ultimately upload failures.Manual Content-Type setting causing boundary errors
When you manually specify themultipart/form-data; text/csvrequest header, you're overriding the header automatically generated by the browser. Browsers normally add a randomboundary(delimiter) to distinguish between fields in FormData. Without this boundary, the server can't parse your form data at all, hence the "multipart boundary not found" error.
Practical Solutions
Solution 1: Force MIME type for File fields
Modify your buildFormData function to manually specify the correct MIME type when adding File-type fields, ensuring the file type is unified as text/csv across all systems:
export function buildFormData(request) { const formData = new window.FormData(); for (const name in request) { const value = request[name]; // Identify File objects and force MIME type setting if (value instanceof File) { // Determine based on file suffix to ensure CSV files use text/csv const targetMimeType = value.name.toLowerCase().endsWith('.csv') ? 'text/csv' : value.type; // The third parameter specifies the file name while ensuring correct MIME type formData.append(name, value, { name: value.name, type: targetMimeType }); } else { formData.append(name, value); } } return formData; }
Then keep your upload function as-is, do not manually set Content-Type—the browser will automatically generate a request header with the correct boundary:
export function checkImported(file) { const formData = UTILS.buildFormData({ file }); return fetch(`${ServerConst.SERVER_CONTEXT_PATH}/import/check`, { method: 'POST', body: formData, }).then(response => response.json()); }
Solution 2: Handle the File field directly in the upload function
If you don't want to modify the universal buildFormData function, you can process the file field directly during upload:
export function checkImported(file) { const formData = new FormData(); // Directly specify text/csv type for the file field formData.append('file', file, { type: 'text/csv', name: file.name }); return fetch(`${ServerConst.SERVER_CONTEXT_PATH}/import/check`, { method: 'POST', body: formData, // Also do not manually set Content-Type }).then(response => response.json()); }
Key Notes
- Never manually set the
multipart/form-datarequest header unless you fully understand how to generate and match the boundary—let the browser handle this automatically, it's the most reliable approach. - You can add an extra layer of validation on the server side to ensure the received file type is
text/csv, avoiding errors in subsequent business logic.
内容的提问来源于stack exchange,提问作者Hearen

