节点javascript文件上传在远程服务器上不起作用

时间:2020-10-25 23:09:53

标签: node.js file-upload apollo-server

在访问本地主机的本地开发机上,即使将网络设置更改为“慢3G”,以下代码也可以正常工作。但是,在我的VPS上运行时,它无法处理服务器上的文件。这是我尝试过的两个不同的代码块(同样,它们都可以在访问本地主机的本地开发机上正常工作)

  profilePicUpload: async (parent, args) => {
     const file = await args.file;
     const fileName = `user-${nanoid(3)}.jpg`;
     const tmpFilePath = path.join(__dirname, `../../tmp/${fileName}`);

     file
        .createReadStream()
        .pipe(createWriteStream(tmpFilePath))
        .on('finish', () => {
          jimp
            .read(`tmp/${fileName}`)
            .then(image => {
              image.cover(300, 300).quality(60);
              image.writeAsync(`static/uploads/users/${fileName}`, jimp.AUTO);
            })
            .catch(error => {
              throw new Error(error);
            });
        });
}

此代码块似乎没有等待足够长的时间来完成文件上传,因为如果我检查VPS上的存储位置,则会看到以下信息:

我也没有运气尝试过以下方法:

profilePicUpload: async (parent, args) => {
      const { createReadStream } = await args.file;
      let data = '';

      const fileStream = await createReadStream();

      fileStream.setEncoding('binary');

// UPDATE: 11-2
      let i = 0; 
      fileStream.on('data', chunk => {
        console.log(i);
        i++;
        data += chunk;
      });

      fileStream.on('error', err => {
        console.log(err);
      });
// END UPDATE


      fileStream.on('end', () => {
        const file = Buffer.from(data, 'binary');
        jimp
          .read(file)
          .then(image => {
            image.cover(300, 300).quality(60);
            image.writeAsync(`static/uploads/users/${fileName}`, jimp.AUTO);
          })
          .catch(error => {
            throw new Error(error);
          });
      });
}

使用此代码,我什至没有得到部分文件。

jimp是用于图像处理的JS库。

如果任何人有任何提示使其正常工作,我将非常感谢。如果我缺少一些信息,请告诉我。

1 个答案:

答案 0 :(得分:1)

我可以通过参考以下文章找出解决方案:https://nodesource.com/blog/understanding-streams-in-nodejs/

这是我最终的工作代码:

const { createWriteStream, unlink } = require('fs');
const path = require('path');
const { once } = require('events');
const { promisify } = require('util');
const stream = require('stream');
const jimp = require('jimp');

profilePicUpload: async (parent, args) => {
      // have to wait while file is uploaded
      const { createReadStream } = await args.file;

      const fileStream = createReadStream();
      const fileName = `user-${args.uid}-${nanoid(3)}.jpg`;
      const tmpFilePath = path.join(__dirname, `../../tmp/${fileName}`);
      const tmpFileStream = createWriteStream(tmpFilePath, {
        encoding: 'binary'
      });

      const finished = promisify(stream.finished);

      fileStream.setEncoding('binary');

      // apparently async iterators is the way to go
      for await (const chunk of fileStream) {
        if (!tmpFileStream.write(chunk)) {
          await once(tmpFileStream, 'drain');
        }
      }

      tmpFileStream.end(() => {
        jimp
          .read(`tmp/${fileName}`)
          .then(image => {
            image.cover(300, 300).quality(60);
            image.writeAsync(`static/uploads/users/${fileName}`, jimp.AUTO);
          })
          .then(() => {
            unlink(tmpFilePath, error => {
              console.log(error);
            });
          })
          .catch(error => {
            console.log(error);
          });
      });

      await finished(tmpFileStream);
}
相关问题