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

React Native CameraRoll.getPhotos返回uri无法通过Web API上传求助

解决React Native上传图片到C#后端无法获取Request.Files的问题

我来帮你排查这个问题,核心原因是你FormData的使用方式不符合文件上传的规范,再加上几个细节没处理好,咱们一步步解决:

1. 修正FormData的文件添加逻辑

你现在把整个图片数组直接塞到file字段里了,这完全不对——multipart/form-data上传多个文件时,得逐个把文件append到FormData,后端才能识别为文件集合。调整代码如下:

const postData = new FormData();
// 遍历图片数组,逐个添加文件
images.forEach((image) => {
  // 注意:CameraRoll返回的uri在Android上一般是file://开头,iOS可能是assets-library://,后面会说处理方式
  const formFile = {
    uri: image.uri,
    name: image.name,
    type: image.type
  };
  // 如果后端要接收多个文件,这里的key用`file`或者`file[]`都可以,C#后端两种都能识别
  postData.append('file', formFile);
});
// 其他字段正常append
postData.append('userid', this.user._id);
postData.append('time', moment().format('YYYY-M-D H:mm:ss'));
postData.append('group', this.groupID);

2. 处理React Native的uri格式问题

CameraRoll拿到的uri在iOS和Android上格式不一样,直接用可能导致上传失败:

  • Android:返回的uri一般是file:///storage/...这种,直接用就行
  • iOS:返回的是assets-library://开头的uri,这种路径无法直接被FormData读取,得转换成本地文件路径。可以用react-native-fs库来转换:
import RNFS from 'react-native-fs';

// 封装一个转换iOS uri的方法
async function convertToFileUri(uri) {
  if (uri.startsWith('assets-library://')) {
    const fileName = `${Date.now()}.${uri.split('.').pop()}`;
    const filePath = `${RNFS.DocumentDirectoryPath}/${fileName}`;
    // 复制assets文件到本地可访问路径
    await RNFS.copyAssetsFileIOS(uri.replace('assets-library://', ''), filePath, 0, 0);
    return `file://${filePath}`;
  }
  return uri;
}

// 生成images数组时调用这个方法
const images = await Promise.all(messages.map(async k => {
  const fileUri = await convertToFileUri(k.image);
  return { 
    uri: fileUri, 
    name: k.filename, 
    type: mime.lookup(k.filename), 
  };
}));

3. 后端C#的接收代码要对应

如果你的后端是ASP.NET Core,要通过Request.Form.Files获取文件;如果是旧版ASP.NET,用Request.Files。示例代码:

ASP.NET Core版本

[HttpPost("postImage")]
public async Task<IActionResult> PostImage()
{
    // 获取上传的所有文件
    var uploadedFiles = Request.Form.Files;
    // 获取其他表单字段
    var userId = Request.Form["userid"].ToString();
    var time = Request.Form["time"].ToString();
    var groupId = Request.Form["group"].ToString();

    if (uploadedFiles.Count == 0)
    {
        return BadRequest("没有上传任何文件");
    }

    // 遍历处理每个文件
    foreach (var file in uploadedFiles)
    {
        // 示例:保存文件到服务器
        var savePath = Path.Combine("你的存储路径", file.FileName);
        using (var stream = new FileStream(savePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
    }

    return Ok("文件上传成功");
}

旧版ASP.NET版本

[HttpPost]
public ActionResult PostImage()
{
    var uploadedFiles = Request.Files;
    var userId = Request.Form["userid"];
    // ... 其他字段获取

    if (uploadedFiles.Count == 0)
    {
        return Json(new { success = false, msg = "没有上传任何文件" });
    }

    foreach (HttpPostedFileBase file in uploadedFiles)
    {
        // 处理文件逻辑
        file.SaveAs(Server.MapPath("~/Uploads/" + file.FileName));
    }

    return Json(new { success = true });
}

4. 去掉axios里手动设置的Content-Type

你现在手动设置了'Content-Type': 'multipart/form-data',这会导致axios丢失自动生成的boundary分隔符,后端根本解析不了请求。直接删掉这个设置,axios会自动处理正确的请求头:

axios.post(WebAPI.url.chat.postImage, postData, {
    headers: {
        access_token: this.user.access_token
        // 删掉Content-Type这一行!
    },
})
.then(response => {
    console.log(response.data)
})
.catch(error => {
    console.log(error)
})

最后再检查一遍

  • 确保每个文件都是单独append到FormData的,不是塞数组
  • iOS的uri已经转换成file://开头的本地路径
  • 后端用正确的方式获取文件(Core用Request.Form.Files,旧版用Request.Files)
  • 没有手动设置Content-Type

按这些步骤调整后,后端应该就能正常获取到上传的文件了!

内容的提问来源于stack exchange,提问作者12343954

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:45:11