Flutter使用Dio/http.MultipartRequest上传图片遇301状态错误求助
Flutter图片上传301错误问题处理
问题概述
开发首个Flutter项目,通过PHP REST API对接MySQL服务器,需将Android/iOS设备相册中的图片上传至服务器目录https://<my web site>/wp-content/my_app/avatars。尝试http.Request、Dio、http.MultipartRequest三种上传方式,均返回301永久重定向错误。网站托管于Cloudflare,临时将目标目录权限设为777未解决问题。
获取图片路径代码片段
// 代码片段提取 XFile? imageFile; imageFile = await picker.pickImage(source: ImageSource.gallery); _pathAvatar = imageFile!.path; updateUser(_pathAvatar);
上传函数代码
uploadImage(String filePath) async { dio = new Dio(); var url = "https://<my web site>/upload"; // API密钥示例格式: 7940e6b5-xxxx-xxxx-xxxx-6883ab87a566 var token = "<我的APP API密钥>"; Map<String, String> headers = { 'Authorization': 'Bearer $token', "Content-Type": "multipart/form-data", "X-Requested-With": "XMLHttpRequest" }; await dio.post(url, data: filePath, options: Options( method: 'POST', headers: headers, responseType: ResponseType.json // 或ResponseType.JSON )).whenComplete(() { print('上传完成'); }).catchError((onError) { print(onError); }); }
Dio错误信息
DioException [bad response]: 抛出此异常是因为响应状态码为301,且RequestOptions.validateStatus配置为此状态码抛出异常。
状态码301含义:"重定向:需要进一步操作才能完成请求"
解决此异常通常需要检查并修复请求代码,或修复服务器端代码。
301响应详情
<html><head> <title>301 Moved Permanently</title> </head><body> <h1>Moved Permanently</h1> <p>The document has moved <a href="<my web site>">here</a>.</p> </body></html>
完整响应头
connection: keep-alive alt-svc: h3=":443"; ma=86400 location: https://www.mywebsite.com/wp-content/my_app/avatars/**/* date: Sun, 10 Mar 2024 18:14:05 GMT transfer-encoding: chunked strict-transport-security: max-age=16000000 nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800} cf-ray: 8625484e8c9e2ba2-FRA report-to: {"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v3?s=Ncs56WKcsVkdO%2F1Dk4ZmDM3Ysc%2FWYFuJ68ESqzSQdJtJTkNH54uqSGxi9cQHSysaAUsffg%2BTbA2zuy0%2FGSq5zBUH8ksxdIFXCIQmqGARb0Q%2FIkJXfnYsgiM8zjIr0xOrhYZzD4ZotA%3D%3D"}],"group":"cf-nel","max_age":604800} cf-cache-status: DYNAMIC content-type: text/html; charset=iso-8859-1 server: cloudflare
注:响应头的location字段末尾带有斜杠,但请求URL中未包含。
解决步骤
- 修正请求URL:从响应头的
location可以看出,服务器将请求重定向到了带www的域名,且路径指向avatars目录。需将上传请求的URL改为重定向目标的正确地址,确保域名一致(统一带www或不带www),同时确认PHP API的实际端点路径是否正确(应指向处理上传的API脚本,而非直接指向存储目录)。 - 配置Dio自动跟随重定向:在Dio的
Options中开启重定向跟随,并调整状态码验证规则:
options: Options( method: 'POST', headers: headers, responseType: ResponseType.json, followRedirects: true, validateStatus: (status) { // 允许3xx状态码不抛出异常 return status! < 500; } )
- 检查服务器端重定向规则:登录Cloudflare后台,查看页面规则或重定向规则是否误将
/upload路径重定向到了avatars目录;同时检查PHP上传脚本是否存在错误的重定向逻辑。 - 修复Multipart请求格式:当前代码直接传入文件路径不符合
multipart/form-data的要求,需将文件包装为FormData对象:
FormData formData = FormData.fromMap({ "avatar": await MultipartFile.fromFile(filePath, filename: "avatar.jpg"), }); // 上传时传入formData await dio.post(url, data: formData, options: Options(...) )
内容的提问来源于stack exchange,提问作者Massimiliano Longo
相关产品推荐
相关产品推荐

