【问题标题】:NodeJS Download and Upload In-Memory Stream AsynchronouslyNodeJS 异步下载和上传内存流
【发布时间】:2020-10-11 22:47:22
【问题描述】:

问题
您如何在 NodeJS 中完全通过 Streams(不使用文件系统)异步下载和(可恢复/多部分)上传大型 MP4 文件?

场景
我正在编写一个类文件,该文件涉及纯粹通过内存从 URL 流式下载到 Google Drive 或 Dropbox。

**文件大小在下载和上传之前是已知的。

视觉

==============
      ^(5%)  ^(10%)
Downloader

      ==============
            ^(5%)  ^(10%)
       Uploader

要求

  1. 通过内存流传输(不在文件系统上存储任何内容)
  2. 上传应该是多部分可恢复的,并且范围可以从 5 Mb 到 > 20 Gb。
  3. 如果下载或上传失败,应该有一定的重试次数。

好奇心

  1. 双工流(例如直通)是执行此操作的正确方法吗?
  2. 如上图所示,您如何在异步方法中传达 Content-Length

伪代码

const axios = require('axios');
const stream = require('stream');
const passtrough = new stream.PassThrough();

let sample = VideoAPI.get() // pass id
//sample.url // url located here
//sample.size // size is known prior to download or upload
//sample.contentType // content-type is known prior to download

//Download sample via Axios
axios.get(sample.url, {
    responseType: "stream"
}).then((response) => {
    //TODO: Pipe to Google Drive
    console.log('response', response)
}).catch((error) => {
    console.error(error)
})

研究

  1. Upload to Google Drive w/ Passthrough Stream
  2. Resumable upload
  3. Webshot to Google Drive without Intermediate File

【问题讨论】:

  • 有什么问题?你在挣扎什么?
  • @Marc 我很困惑如何在异步管道流中的多部分上传中正确传达 Content-Length。
  • 异步方法在这里不起作用。您必须先下载所有文件,操作“文件”或在内存流中,计算总长度并再次上传文件

标签: node.js google-drive-api axios


【解决方案1】:

我认为你需要这样的东西:

request.get(sourceUrl).pipe(request.post(targetUrl))

在此方案中,数据将从 sourceUrl 流向 targetUrl,但不需要保存在服务器上的临时文件中。

如需澄清,请访问request#streaming

【讨论】:

  • 我很欣赏它的优雅。我注意到我很好奇如何处理文件大于 1 GB 的多部分或可恢复上传到目标 URL,并考虑标题,尤其是 Content-Length 在上传中的通信方式。谢谢分享。
  • 我发现了这个发现:“请求也可以通过管道传递给自己。这样做时,内容类型和内容长度会保留在 PUT 标头中。”这似乎在满足上述好奇心方面可能走在正确的轨道上,但我不确定并且会测试。
  • 我用request-progress 库实现了这个,它的工作就像一个魅力。感谢您分享您的见解,朋友。
  • @pixelbobby 我很高兴听到这个消息。我们在这里互相帮助。祝你好运:)
【解决方案2】:
const formData = new FormData();

axios.get(sample.url, {
    responseType: "stream"
}).then((response) => {
    //TODO: Pipe to Google Drive
    // you can directly put the response stream onto the formData object.
    formData.append('files', response.data);
    return axios.post(googleURL,{headers:{...formData.getheaders()}, data: formData});
.then((response)=>{
//response from google
console.log(response.data);
})
}).catch((error) => {
    console.error(error)
})

//N.B. The response.data steam will be appended to the formData object, this is all done in memory. Make sure the responseType is set to stream.

【讨论】:

  • 请对您的回答进行详细解释,以便下一位用户更好地理解您的回答。
猜你喜欢
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 2011-09-07
  • 2017-12-24
  • 1970-01-01
  • 2019-05-29
相关资源
最近更新 更多