节点应用将文件从gcloud存储下载到客户端

时间:2019-04-30 19:30:42

标签: node.js google-cloud-storage

似乎这样的罐头答案应该是某种形式的,但我什么也找不到。

因此,情况是:

  • 我有一个网页列出要下载的文件
  • 文件位于gcloud存储中
  • 我有一个节点服务器(快速)应用程序可以访问gcloud并获取文件。

网页js看起来像这样:

<script>
  function downloadFile(client, fn) {
    var x=new XMLHttpRequest();
      x.open("GET", "https://<domain>/fetch/" + client + '/' + fn, true);
      x.responseType = 'blob';
      x.onload=function(e){download(x.response, fn, "<content-type>" ); }
      x.send();
  }
</script>

它正在使用所需的提取参数对服务器进行XMLHttpRequest()的直接处理。

节点js的相关部分如下所示:

app.get('/fetch/:client/:filename', async function(req,rsp) {
  try {
    const storage = new Storage();
    const fileLoc = req.params.client + '/' + req.params.filename

    const options = {
      destination: './' + req.params.filename,
    };

    // Downloads the file
    let file = await storage
      .bucket('<bucket-name>')
      .file(fileLoc)

    let rstream = await file.createReadStream()
    .on("error", (err) => {
      console.log(" --> rstream error: " + err)
    })
    .on("response", (strRsp) => {
      console.log(' --> response received, sending headers.')
      rsp.setHeader('Content-Length', strRsp.headers['content-length'])
      rsp.setHeader('Content-Type', strRsp.headers['content-type'])
      rsp.header('Content-Disposition', 'attachment; filename=' + req.params.filename)
    })
    .on("end", () => {
      console.log(' --> end received.')
      rsp.status(200).end()
      return true
    })
    .pipe(rsp)

  } catch(err) {
    console.log('download error: ' + err)
    rsp.status(400).send('failed') 
  } 
});

问题是它可以工作,但是会在弹出“另存为”对话框之前(无提示)下载整个文件。

有没有一种方法可以在下载之前建立保存对话框? (也许我需要在客户端执行“ content-disposition”标头...?)

如果没有,有没有办法将进度反映回网页js,以便我可以建立一个对话框并显示进度,也许还有一个取消按钮,直到完成并显示另存为对话框?

1 个答案:

答案 0 :(得分:0)

好的,我接受了后一个答案。执行以下操作:

  • 根据下载请求,弹出一个包含下载信息的加载对话框。
  • 使用XMLHttpRequest实例注册进度回调
  • 在对话框中显示进度信息
  • 对话框具有一个“取消”按钮,该按钮在XMLHttpRequest实例上调用“ abort()”
  • 完成(或中止)后,请更新对话框,然后通过超时将其关闭。