首页 > 解决方案 > Busboy 文件事件未触发,在请求正文中接收文件作为缓冲区

问题描述

我正在开发一个使用react-dropzone钩子实现拖放文件上传功能的反应应用程序。然后我通过 POST 请求将文件发送到 firebase 云功能。

我正在使用 BusBoy 将接收到的文件写入 tmpdir 并将接收到的文件上传到 firebase 存储。

BusBoy 文件事件未在我的云功能中触发。

前端


const onDrop = useCallback((acceptedFiles) => {
    // Check whether excel file is uploaded
    if (
      acceptedFiles[0].type == `application/vnd.ms-excel`.trim() ||
      acceptedFiles[0].type ==
        `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    `.trim()
    ) {
      auth.currentUser.getIdToken().then((token) => {
        let bodyFormData = new FormData();
        bodyFormData.append('file', acceptedFiles[0]);
        axiosInstance
          .post('/upload', bodyFormData, {
            crossdomain: true,
            headers: {
              Authorization: `Bearer ${token.toString()}`,
              'Access-Control-Allow-Origin': '*',
              'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
            },
          })
          .then((res) => {
            console.log(res);
          })
          .catch((err) => {
            console.log(err);
          });
      });
    } else {
      setFileTypeError(true);
    }
  }, []);

请求标头内容类型为multipart/form-data; boundary=----WebKitFormBoundaryRWo4LrjStmEjoZll

和表单数据是file:{binary}

在此处输入图像描述

后端

app.post('/upload', verifyAuth, (req, res) => {
  const BusBoy = require('busboy');
  const path = require('path');
  const os = require('os');
  const fs = require('fs');

  const busboy = new BusBoy({ headers: req.headers });

  let tempFileName;
  let fileToBeUploaded = {};

  busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
    console.log('file received');
    const fileExtension = filename.split('.')[filename.split('.').length - 1];
    tempFileName = `bulk-upload-${shortid.generate()}.${fileExtension}`;
    const filePath = path.join(os.tmpdir(), tempFileName);
    fileToBeUploaded = { filePath, mimetype };
    file.pipe(fs.createWriteStream(filePath));
  });

  busboy.on('finish', () => {
    bucket
      .upload(fileToBeUploaded.filePath, {
        resumable: false,
        metadata: {
          metadata: {
            contentType: fileToBeUploaded.mimetype,
          },
        },
      })
      .then(() => {
        return res.status(200).json({ success: true });
      })
      .catch((err) => {
        return res.status(400).json({ error: err });
      });
  });
});

Busboy On file 事件没有被触发。我还检查了req.file,这返回未定义。谁能帮助我哪里出错了?

标签: javascriptnode.jsreactjsbusboyreact-dropzone

解决方案


我遇到了同样的问题,当我将带有 multipart/form 的文件发送到 express firebase 云函数时,文件事件不会触发。我读了其他帖子,建议删除可以从请求中读取文件流的其他中间件,但这对我不起作用,现在我还没有解决这个问题

但是,一种可能的替代方法是使用 Firebase API 首先将图片从客户端应用程序直接上传到存储桶,然后执行一些操作(在我的情况下,将记录保存在数据库中):

 
      var photoRef = storage.ref().child(photoName);

      var uploadTask = photoRef.put(this.post.photo);

      uploadTask.on(
        "state_changed",
        (snapshot) => {
          // Observe state change events such as progress, pause, and resume
          // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
          
        },
        (error) => {
          // Handle unsuccessful uploads
        },
        () => {
          // Handle successful uploads on complete
          
          uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => {
            console.log("File available at", downloadURL);
            db.collection("images")
              .doc(fields.id)
              .set({
                id: fields.id,
                caption: fields.caption,
                location: fields.location,
                date: parseInt(fields.date),
                imageUrl: downloadURL,
              })
              .then(() => {
                console.log("Post added: " + fields.id);
              });
          });
        }
      );

如果您需要对服务器上的文件进行处理,您可以先将其上传到存储桶,然后在云功能上检索它。


推荐阅读