如何将带--data-binary参数的cURL PUT请求转换为Dart HTTP PUT请求上传图片到CDN
问题原因
你之前的实现使用了MultipartRequest,对应multipart/form-data格式的请求,会给请求体自动加上表单边界、字段包裹等额外内容,和curl中--data-binary直接发送文件原始二进制流的逻辑完全不符,所以CDN存储的内容是被表单格式包装过的,自然会出现文件格式错误。
正确实现方案
直接使用普通PUT请求,将文件原始字节作为请求体发送即可,完全模拟--data-binary的效果,代码示例如下:
import 'package:http/http.dart' as http; import 'dart:io'; // 上传逻辑 try { final imageFile = File(_image.path); final uploadUri = Uri.parse('https://storage.bunnycdn.com/storage/path/index.jpeg'); // 替换为你的实际CDN上传路径 final response = await http.put( uploadUri, headers: { 'AccessKey': '<AccessKey>', // 替换为你的实际AccessKey 'Content-Type': 'application/octet-stream', }, // 直接传入文件原始字节作为请求体 body: await imageFile.readAsBytes(), ); if (response.statusCode == 201) { // 上传成功处理 setState(() { isLoading = false; }); } else { // 上传失败处理,可打印响应信息排查问题 print('上传失败,状态码:${response.statusCode},错误信息:${response.body}'); setState(() { isLoading = false; }); } } catch (e) { print('上传异常:$e'); setState(() { isLoading = false; }); }
大文件上传优化(可选)
如果上传的是大体积图片,为了避免一次性读取全部字节到内存占用过高,可以用流的方式发送:
try { final imageFile = File(_image.path); final uploadUri = Uri.parse('https://storage.bunnycdn.com/storage/path/index.jpeg'); final request = http.Request('PUT', uploadUri); request.headers.addAll({ 'AccessKey': '<AccessKey>', 'Content-Type': 'application/octet-stream', 'Content-Length': imageFile.lengthSync().toString(), // 可选,提前告知CDN文件大小 }); // 将文件流写入请求体 await request.sink.addStream(imageFile.openRead()); final response = await request.send(); if (response.statusCode == 201) { setState(() { isLoading = false; }); } else { print('上传失败,状态码:${response.statusCode}'); setState(() { isLoading = false; }); } } catch (e) { print('上传异常:$e'); setState(() { isLoading = false; }); }
说明
上述代码和你提供的curl命令逻辑完全对齐,没有额外的内容包装,直接发送图片的原始二进制数据到CDN,上传后的文件格式不会出现异常。
内容的提问来源于stack exchange,提问作者mohamed mostapha
相关产品推荐
相关产品推荐

