You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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中未包含。

解决步骤

  1. 修正请求URL:从响应头的location可以看出,服务器将请求重定向到了带www的域名,且路径指向avatars目录。需将上传请求的URL改为重定向目标的正确地址,确保域名一致(统一带www或不带www),同时确认PHP API的实际端点路径是否正确(应指向处理上传的API脚本,而非直接指向存储目录)。
  2. 配置Dio自动跟随重定向:在Dio的Options中开启重定向跟随,并调整状态码验证规则:
options: Options(
    method: 'POST',
    headers: headers,
    responseType: ResponseType.json,
    followRedirects: true,
    validateStatus: (status) {
      // 允许3xx状态码不抛出异常
      return status! < 500;
    }
)
  1. 检查服务器端重定向规则:登录Cloudflare后台,查看页面规则或重定向规则是否误将/upload路径重定向到了avatars目录;同时检查PHP上传脚本是否存在错误的重定向逻辑。
  2. 修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 01:05:20