首页 > 解决方案 > 下载大文件并继续使用nodejs上传到minio,杀死我的服务?

问题描述

我有一个用 NodeJS 构建的 API,在那个 API 中有一个过程,我使用模块 request-promise 下载一个大文件,然后将它作为一个新的缓冲区上传到 minio。但是我有一个问题,如果文件超过 80-100MB 并且它的 NodeJS 在服务器上被杀死,我的 API 总是崩溃,如何处理它?

此功能是下载文件并将其转换为缓冲区:

const convertLink = async link => {
  const options = {
    uri: link,
    encoding: null,
    headers: {
      'Content-type': 'application/octet-stream'
    }
  };
  const res = rp.get(options)
    .then((body) => {
      console.log(body)
      const a = new Buffer.from(body);
      return a;
    })
    .catch(err => {
      console.log(err)
      return err;
    });
  return res;
};

这是从 miniosdk 上传文件到 minio 的功能:

const streamUpload = async (bucketName, objectName, newBuffer) => {
    try {
        const isUploaded = await minioClient.putObject(bucketName, objectName, newBuffer);
        if (isUploaded) {
            return isUploaded;
        }
    } catch (err) {
        return err;
    }
};

标签: node.jsrequest-promiseminio

解决方案


我认为这里的问题是您正在下载文件并将其保存在内存中,然后将其上传到您的 minioClient。不建议将其用于大文件。您应该将该文件下载为流,然后也将其上传为流。将大文件保存在内存中可能是杀死 node.js 服务器的原因。

您可以尝试以下示例,其中我正在使用requestnpm 库并下载文件并将其作为流保存到临时位置,然后从该临时位置读取文件并上传到另一个 URL:-

下载文件:-

const downloadFile = async (url) => {
    try {

        let tempLocation = "./temp/";
        let fileName="myfile";
        return new Promise((resolve, reject) => {
            request
                .get(url)
                .on('response', function (response) {
                     console.log(response.statusCode) // 200
                     console.log(response.headers['content-type']) 
                })
                .on('error', function (error) {
                    console.log('downloading error', error)
                    reject()
                })
                .on('end', async function () {
                    console.log("donwload finished")
                    resolve();
                })
                .pipe(fs.createWriteStream(tempLocation + '/' + fileName))
        });

    } catch (error) {
        console.log("error in downloadFile", error)
        throw error;
    }
}

现在您可以将文件作为流上传到您的 minioClient。您可以使用fs.createReadStream(file)从该临时位置将文件作为流数据读取。


推荐阅读