Flutter Web上传图片返回200状态码但文件损坏 多实现方案均失效
问题根因
你使用的是对象存储的预签名URL(Signed URL)进行上传,这类上传接口要求直接PUT文件的原始二进制数据流,而你当前两种实现都将文件封装进了FormData/MultipartRequest结构中,服务端会将FormData的边界标识、字段头等额外信息一同写入文件,最终导致图片格式损坏。
修正后的代码实现
1. 基于dio的上传修正
uploadImageWeb(Uint8List fileBytes, String? fileName) async { var dioo = Dio(); try { String? sUrl = await _profileController.getSignedUrl("profile"); if (sUrl == null) { print("Signed Url is null"); return; } _profileController.isPicUploading(true); // 从文件名获取正确的MIME类型 String? mimeType = lookupMimeType(fileName ?? ''); var response = await dioo.put( sUrl, data: Stream.fromIterable(fileBytes.map((e) => [e])), // 直接传二进制流 options: Options( headers: { Headers.contentTypeHeader: mimeType ?? 'image/jpeg', // 正确设置Content-Type请求头 Headers.contentLengthHeader: fileBytes.length, // 必须设置内容长度 "Authorization": "Bearer", }, ), ); if (response.statusCode == 200) { print("上传成功,状态码:${response.statusCode}"); } else { print("上传失败,状态码:${response.statusCode}"); } } catch (e) { print("上传异常:$e"); } finally { _profileController.isPicUploading(false); } }
2. 基于http的上传修正
imageUploadWithHttp(Uint8List? fileBytes, String? fileName) async { if (fileBytes == null || fileName == null) return; try { String? sUrl = await _profileController.getSignedUrl("profile"); if (sUrl == null) { print("Signed Url is null"); return; } _profileController.isPicUploading(true); String? mimeType = lookupMimeType(fileName); // 直接使用普通PUT请求,不要用MultipartRequest var response = await http.put( Uri.parse(sUrl), body: fileBytes, // 直接传二进制字节数组 headers: { Headers.contentTypeHeader: mimeType ?? 'image/jpeg', Headers.contentLengthHeader: fileBytes.length.toString(), "file-name": fileName, }, ); if (response.statusCode == 200) { print("上传成功"); } else { print("上传失败,状态码:${response.statusCode}"); } } catch (e) { print("上传异常:$e"); } finally { _profileController.isPicUploading(false); } }
额外验证步骤
- 上传前可以先计算本地文件字节的MD5值,上传完成后从服务端下载文件重新计算MD5,两者一致则说明传输正确
- 确认预签名URL生成时指定的Content-Type和上传时传入的Content-Type一致,部分云存储会校验该参数匹配性
- 不要在请求头中加
Access-Control-Allow-Origin,该字段是服务端返回的响应头,请求侧携带无意义反而可能导致跨域错误
内容的提问来源于stack exchange,提问作者al_rus
相关产品推荐
相关产品推荐

