如何在Node.js和graphql-upload中通过管道传输多个流以将文件/流上传到Cloudinary或其他存储提供商? 代码

问题描述

我的阿波罗服务器正在使用graphql-upload软件包,其中包括对GraphQL端点的文件上传支持。但是他们只记录了有关上传单个文件的信息。但是我们需要多个文件上传支持。好吧,我将流作为数组。但是,每当我为每个流 createReadStream 并将它们通过管道传送到cloudinary上载程序var时,它只会上载最后创建的流,而不是上载每个流。

代码

  // graphql reolver
const post = async (_,{ post },{ isAuthenticated,user }) => {
  if (!isAuthenticated) throw new AuthenticationError("User unauthorized");
const files = await Promise.all(post.files);
 let file_urls = []; 
 const _uploadableFiles = cloudinary.uploader.upload_stream({ folder: "post_files" },(err,result) => {
     console.log("err:",err);
     console.log("result:",result);
      if (err) throw err;
        file_urls.push({
            url: result.secure_url,public_id: result.public_id,file_type: result.Metadata,});
     return result;
   }
 );
files.forEach(async (file) => await file.createReadStream().pipe(_uploadableFiles));

.... other db related stuff
}

此后,我从上载的文件获取Secure_URL,该文件由cloudinary upload_stream函数回调返回。但这只给了我一个流的属性,它是所有流中的最后一个在这种情况下请帮助我。有什么方法可以传送多个流?

解决方法

不是制作一个const上传流,而是将其变成了一个工厂函数,该函数会在每次调用管道时返回一个上传流

使用array map,以便获得可以在Promise.all中使用的数组

每个文件都应一个接一个地上传到各自的上传流中,并在完成所有操作后将生成的文件url信息附加到file_urls(在成功回调后)。Promise.all将解决,并且代码可以恢复做其他与数据库有关的事情

const post = async (_,{ post },{ isAuthenticated,user }) => {

  if (!isAuthenticated) throw new AuthenticationError("User unauthorized");
  const files = await Promise.all(post.files);
  let file_urls = []; 

  function createUploader(){
    return cloudinary.uploader.upload_stream({ folder: "post_files" },(err,result) => {
       console.log("err:",err);
       console.log("result:",result);
        if (err) throw err;
          file_urls.push({
              url: result.secure_url,public_id: result.public_id,file_type: result.metadata,});
       return result;
     }
    );
  }

  await Promise.all( files.map(async (file) => await file.createReadStream().pipe(createUploader())) ); //map instead of forEach

  //.... other db related stuff
}