When implementing video uploads from Camera in our Flutter web application, we initially used http.MultipartRequest to send the video file. However, we ran into multiple issues with the backend, which was using Express.js + Multer for handling file uploads.
Initial Dart Code (That Didn't Work)
final request = http.MultipartRequest('POST', uri);
request.headers.addAll(headers);
request.files.add(await http.MultipartFile.fromBytes(fileType,
bytes, contentType: mediaType));
final response = await request.send();
NodeJS Multer Code
Our backend was using Express.js with Multer to handle the video uploads:
const upload = multer({
dest: 'uploads/',
limits: {
fileSize: 100 * 1024 * 1024, // ✅ Set max file size to 100MB
fieldSize: 25 * 1024 * 1024, // ✅ Increase field size limit (for form fields)
}
});
app.post('/upload', upload.single('videoResume'), (req, res) => {
if (!req.file) {
return res.status(400).send('No file uploaded.');
}
console.log("File uploaded: ${req.file.originalname}");
res.status(200).send('File uploaded successfully.');
});
Issues Faced with Multer in Node.js
1️⃣ File Length Too Long Issue
Multer would sometimes reject the request, stating that the file was too long or exceeding expected limits.
Even after increasing fileSize in Multer's configuration, the issue persisted.
2️⃣ req.file Undefined Issue
Multer did not recognize the uploaded file at all.
req.file was undefined, meaning the file wasn't being parsed correctly.
The request headers and structure seemed correct, yet the backend couldn't extract the file.
Solution: Writing a Custom Multipart Request
After multiple failed attempts we decided to manually construct the multipart request, ensuring that:
- ✅ The file is properly wrapped in a multipart boundary.
- ✅ The correct Content-Type is used.
- ✅ The request format is exactly as expected by the backend.
Final Working Dart Code (Manual Multipart Request)
Future<dynamic> multipartRequestWebVideo(
String url, XFile videoFile, String fileType) async {
try {
final bytes = await videoFile.readAsBytes();
final boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'; // Random boundary string
final uri = Uri.parse(url);
// Start building the body
String body = '';
body += '--$boundary\r\n';
body += 'Content-Disposition: form-data; name="$fileType"; filename="${videoFile.name}"\r\n';
body += 'Content-Type: video/webm\r\n\r\n';
// Convert the body to a Uint8List (for binary data)
List<int> bodyBytes = []..addAll(utf8.encode(body))..addAll(bytes);
// Append the closing boundary
bodyBytes.addAll(utf8.encode('\r\n--$boundary--\r\n'));
// Get headers from our function (which adds auth tokens, etc.)
var headers = await addHeaders(isMultiPart: true, isStream: true);
// Override necessary headers
headers['Content-Type'] = 'multipart/form-data; boundary=$boundary';
headers['Content-Length'] = bodyBytes.length.toString();
// Send the request
final response = await http.post(
uri,
headers: headers,
body: bodyBytes,
);
} catch (e) {
return {
'error': e.toString(),
};
}
}
Given the limited time we had, we decided to create a custom multipart request from scratch.
Top comments (0)