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

Flutter上传图片至Node.js服务器失败,无法获取图片如何解决?

问题描述

我想把拍摄的图片上传到Node.js服务器并在服务端获取保存,但目前无法实现。相关代码如下:

Flutter 上传代码

_openCameraPicture(BuildContext context) async {
  var image = await ImagePicker().pickImage(source: ImageSource.camera);
  setState(() async {
    selectedImage = File(image!.path);
    if (Network.isConnected) {
      var request = http.MultipartRequest(
          'POST', Uri.parse("${Network.serverUrl}/upload_image"));
      request.fields['title'] = "testImage";
      request.files.add(http.MultipartFile.fromBytes(
          'picture', selectedImage!.readAsBytesSync(),
          filename: selectedImage!.path.split("/").last));
      var response =
          await request.send().then((value) => {Navigator.pop(context)});
      // if (response.statusCode == 200) {
      //   Do something ...
      // }
    }
  });
}

Node.js 服务器配置

router.post("/upload_image", PhoneInfoCtrl.apiUploadImage);

当前服务端处理方法

static async apiUploadImage(req, res, next) {
    try {
         console.log(req);

         res.sendStatus(200);
       
    } catch (error) {
        //res.status(500);
    }
}

请问如何从req中提取图片?Flutter代码是否存在问题?


解决方案

一、Flutter代码优化

  1. 移除setState内的异步逻辑:setState回调是同步执行的,内部写async无意义,还可能导致状态更新异常。将网络请求移到setState外部:
_openCameraPicture(BuildContext context) async {
  var image = await ImagePicker().pickImage(source: ImageSource.camera);
  if (image == null) return; // 处理用户取消拍照的情况
  setState(() {
    selectedImage = File(image.path);
  });
  
  if (Network.isConnected) {
    var request = http.MultipartRequest(
        'POST', Uri.parse("${Network.serverUrl}/upload_image"));
    request.fields['title'] = "testImage";
    request.files.add(http.MultipartFile.fromBytes(
        'picture', selectedImage!.readAsBytesSync(),
        filename: selectedImage!.path.split("/").last));
    var response = await request.send();
    if (response.statusCode == 200) {
      Navigator.pop(context);
    }
  }
}
  1. 添加文件类型标识(推荐):明确指定图片的MIME类型,帮助服务端识别文件:
request.files.add(http.MultipartFile.fromBytes(
    'picture', selectedImage!.readAsBytesSync(),
    filename: selectedImage!.path.split("/").last,
    contentType: MediaType('image', 'jpeg') // 根据实际图片格式调整为png/webp等
));

二、Node.js服务端提取图片

当前服务端未解析multipart/form-data类型的请求,需借助multer中间件处理文件上传:

1. 安装依赖

npm install multer

2. 配置multer并修改路由

在路由文件中引入并配置multer:

const multer = require('multer');
// 配置文件存储路径和命名规则
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads/'); // 确保项目根目录下存在uploads文件夹,否则手动创建
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname); // 用时间戳避免文件名重复
  }
});
const upload = multer({ storage: storage });

修改路由,添加upload.single('picture')中间件(picture需和Flutter端的文件字段名一致):

router.post("/upload_image", upload.single('picture'), PhoneInfoCtrl.apiUploadImage);

3. 修改服务端处理方法

从req.file中获取上传的图片信息:

static async apiUploadImage(req, res, next) {
    try {
        if (!req.file) {
            return res.status(400).send('未上传图片');
        }
        // req.file包含图片的存储路径、文件名、大小等信息
        console.log('图片上传成功:', req.file);
        // 可在此处将文件路径存入数据库或做其他业务处理
        res.status(200).send({
            message: '图片上传成功',
            filePath: req.file.path
        });
    } catch (error) {
        console.error('上传失败:', error);
        res.status(500).send('图片上传失败');
    }
}

注意事项

  • 确保Node.js项目根目录下的uploads文件夹存在,否则multer会抛出错误。
  • 若存在跨域问题,可在Node.js中安装cors中间件解决。

内容的提问来源于stack exchange,提问作者Javad-M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:20:27