【问题标题】:how to upload file saved in memory by multer to another API如何将multer保存在内存中的文件上传到另一个API
【发布时间】:2018-04-09 02:11:57
【问题描述】:

我有 2 个单独的 NodeJS API,它们使用 multer 将文件保存在 内存 中。

我的 express 中间件是这样的

import multer from 'multer';
const storage = multer.memoryStorage();

export default multer({ storage }).single('image');

我能够成功接收到保存在内存中的文件,所以我的 req.file.image 看起来像这样

{ 
  fieldname: 'image',
  originalname: 'image-2017-08-28-13-47-31-218.png',
  encoding: '7bit',   mimetype: 'image/png',
  buffer: <Buffer 89 50 4e 47 0d 0a 1a 0 ... >, 
  size: 493181
}

收到文件后,在 first API 上,我需要将它发送到同样使用 multersecond API >快递

function secondApiReceiveImage(req, res) {
  console.log(req.file)
  console.log(req.files)
  console.log(req.body)
  res.send('ok');
}

我尝试使用以下实现发送

通过https://github.com/request/request#multipartform-data-multipart-form-uploads

import request from 'request';

function firstApiReceiveImage(req, res) {
  const options = {
    url:'http://SECOND_API/api/image',
    formData: { image: req.file.buffer }
  };
  request.post(options, (err, httpResponse, body) => {
    console.log('err', err);
    console.log('body', body);
  });
}

在这种情况下,req.filereq.filesreq.body的日志都是未定义的 关于 secondApiReceiveImage API 处理函数

我的下一次尝试是https://github.com/form-data/form-data

import multer from 'multer';
const storage = multer.memoryStorage();

export default multer({ storage }).single('image');

function firstApiReceiveImage(req, res) {
  const CRLF = '\r\n';
  const form = new FormData();
  const opts = {
    header: `${CRLF} + '--' + ${form.getBoundary()} + ${CRLF} + 'X-Custom-Header: 123' + ${CRLF} + ${CRLF}`,
    knownLength: 1
  };

  form.append('image', req.file.image.buffer, opts);
  form.submit('http://SECOND_API/api/image', (err, res) => {
    console.log('err', err);
    console.log('res', res);
  });
}

我得到了同样的结果,undefined for req.file, req.files & req.body在第二个 API 上

这些是我除了 multer BTW 之外的两个 API 的中间件

app.use(compression());
app.use(helmet());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

如果我可以将文件保存在第一个 API 上,我本来可以过上更轻松的生活,但在这种情况下我们不能保存到磁盘:(

对我有什么建议吗?

【问题讨论】:

    标签: node.js express file-upload multer


    【解决方案1】:

    我偶然发现了同样的问题,这就是我设法提出的问题。

    首先,我使用 form-data 包来模拟服务器端的 FormData 数据结构,这里是执行此操作的 util 文件。

        const FormData = require('form-data')
        const formData = new FormData()
        const config = {
           headers: {
             'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`
           }
        }
        export default { data: formData, config }
    

    这是我的 node.js api 文件

    
    import formSet from '../utils/formData'
    
    const multer = require('multer')
    const upload = multer()
    
    const { Router } = require('express')
    const router = Router()
    
    ......
    
    router.post('/api/images', upload.single('image'), async (req, res) => {
      formSet.data.append('image', req.file.buffer, { filename: req.file.originalname })
      formSet.data.append('other_data', 'value')
      const response = await axios.post('/images', formSet.data, formSet.config)
    
      .......
    
    })
    

    【讨论】:

    • 我正在尝试与此类似的操作,但它缺少用于设置文件名的第三个参数。谢谢!我用它把一张图片上传到我的后端,然后从那里上传到 Facebook Graph API。如果没有文件名,它就无法工作。
    【解决方案2】:

    团队能够通过首先将缓冲区转换为 Stream 并以不同的方式发送表单数据来解决这个问题。

    import stream from 'stream';
    import rq from 'request-promise';
    
    const { Duplex } = stream;
    
    function bufferToStream(buffer) {
      const duplexStream = new Duplex();
      duplexStream.push(buffer);
      duplexStream.push(null);
      return duplexStream;
    }
    
    async function store({
      originalname, mimetype, size, buffer,
    }) {
      logger.debug(`Saving image name:${originalname} type:${mimetype} size:${size}`);
    
      const formData = {
        image: {
          value: bufferToStream(buffer),
          options: {
            filename: originalname,
            contentType: mimetype,
            knownLength: size,
          },
        },
      };
    
      const options = Object.assign({}, IMAGE_SAVE_ENDPOINT, { formData });
      const response = await rq(options);
      return response.id;
    }
    

    【讨论】:

      【解决方案3】:

      使用Requestformdata应该设置到buffer

      formData: { image: req.file.buffer }
      

      【讨论】:

      • 感谢您的回复!正如您在上面的示例中看到的那样,我已经尝试过这种方法,但它不起作用。第二个 API 似乎没有检测到作为缓冲区发送的文件。不知道为什么:(
      • 啊,你是对的,这里有一个错字。顺便说一句,这有点像 sudo 代码,因为我实际上确实将 2 个图像传递给了第二个 API。我再次检查了代码以确认我确实通过了缓冲区,而不是图像。你试过用真实的 API 模拟这段代码吗?
      • 我使用请求和选项 formData 再次检查了所有可能的拼写错误。仍然没有运气:(
      • 一次传递一张图片。我测试了它的工作原理。所以请放心。
      【解决方案4】:

      我找到了通过缓冲区使用 multer 上传文件而不是本地存储的方法... 这是我的代码....

           var multer = require('multer');
           var storage= multer.memoryStorage();
           var upload = multer({storage: storage});
           var cloudinary = require('cloudinary');
           cloudinary.config({ 
             cloud_name: 'your-cloud-name', 
             api_key: process.env.CLOUDINARY_API_KEY, //your api-key
             api_secret: process.env.CLOUDINARY_API_SECRET //your api-secret
          });
      

      如上所述配置您的 cloudinary 和 multer .....

      从req获取缓冲区如下..

       router.post("/",upload.single('image'),function(req,res){
         var buf = req.file.buffer.toString('base64');
         // Upload code Here
       )};
      

      上传代码:

           cloudinary.uploader.upload("data:image/png;base64," + buf, function(result) {
                //your code here
                console.log(result);
              },{
                folder: 'folder-name' //if you want to store in a folder
              });
      

      结果的输出如下:

            {
            asset_id: 'ed58484fb2bdce823f1b27d*******8',
            public_id: '**************',
            version: 1594455479,
            version_id: '68450****88842ce0aa319603e68d3',
            signature: '3785dbfc3**********883720b',
            width: 750,
            height: 500,
            format: 'png',
            resource_type: 'image',
            created_at: '2020-07-11T08:17:59Z',
            tags: [],
            pages: 1,
            bytes: 70846,
            type: 'upload',
            etag: 'd04dd691de532e941faccda846ef3d76',
            placeholder: false,
            url: 'http://res.cloudinary.com/*****************',
            secure_url: 'https://res.cloudinary.com/*******************'
          }
      

      【讨论】:

        猜你喜欢
        • 2016-10-18
        • 2021-05-21
        • 2018-09-05
        • 2021-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-21
        相关资源
        最近更新 更多