【问题标题】:Node.js stream upload directly to Google Cloud StorageNode.js 流直接上传到谷歌云存储
【发布时间】:2014-07-11 03:51:27
【问题描述】:

我有一个在 Google Compute VM 实例上运行的 Node.js 应用程序,它直接从 POST 请求(而不是通过浏览器)接收文件上传并将传入数据流式传输到 Google Cloud Storage (GCS)。

我正在使用 Restify b/c 我不需要 Express 的额外功能,因为它可以轻松地流式传输传入的数据。

我为该文件创建一个随机文件名,将传入的req 扔到一个简洁的 GCS 小节点包装器(可在此处找到:https://github.com/bsphere/node-gcs),它会向 GCS 发出 PUT 请求。使用 PUT 的 GCS 的文档可以在这里找到:https://developers.google.com/storage/docs/reference-methods#putobject ...它说如果使用chunked transfer encoding,则不需要Content-Length

好消息:文件正在相应的 GCS 存储“桶”内创建!

坏消息:

  1. 我还没有弄清楚如何从 Restify 获取传入文件的扩展名(请注意,我正在手动设置“.jpg”手动设置 content-type)。

  2. 文件出现轻微损坏(几乎可以肯定是因为我在 PUT 请求中做错了什么)。如果我从 Google 下载 POSTed 文件,OSX 会告诉我它已损坏......但是,如果我使用 PhotoShop,它会打开并且看起来很好。

更新/解决方案

正如vkurchatkin 所指出的,我需要解析request 对象,而不是仅仅将整个东西通过管道传输到GCS。在尝试了更轻的busboy 模块后,我认为使用multiparty 更容易。对于动态设置Content-Type,我只是使用Mimer (https://github.com/heldr/mimer),引用传入文件的文件扩展名。重要的是要注意,由于我们正在管道 part 对象,因此必须清除 part.headers。否则,意外信息,特别是content-type,将被传递,并且可能/将与我们试图明确设置的content-type 冲突。

这是适用的修改代码:

var restify = require('restify'),
    server = restify.createServer(),
    GAPI = require('node-gcs').gapitoken,
    GCS = require('node-gcs'),
    multiparty = require('multiparty'),
    Mimer = require('mimer');

server.post('/upload', function(req, res) {

    var form = new multiparty.Form();

    form.on('part', function(part){
        var fileType = '.' + part.filename.split('.').pop().toLowerCase();
        var fileName = Math.random().toString(36).slice(2) + fileType;

        // clear out the part's headers to prevent conflicting data being passed to GCS
        part.headers = null;

        var gapi = new GAPI({
            iss: '-- your -- @developer.gserviceaccount.com',
            scope: 'https://www.googleapis.com/auth/devstorage.full_control',
            keyFile: './key.pem'
        }, 
        function(err) {
            if (err) { console.log('google cloud authorization error: ' + err); }

            var headers = {
                'Content-Type': Mimer(fileType),
                'Transfer-Encoding': 'Chunked',
                'x-goog-acl': 'public-read'
            };

            var gcs = new GCS(gapi);

            gcs.putStream(part, myBucket, '/' + fileName, headers, function(gerr, gres){
                console.log('file should be there!');
            });
        });
    });
};

【问题讨论】:

  • 所以这很好用,但我仍然有点怀疑 GCS 模块(只是因为我的知识水平不是太强),因为它使用了 .pause( ) 和 .resume() ...这不会对文件流产生负面影响吗?
  • 由于 Node 的 (v0.10.24) 流 API 足够智能,可以等待 .pipe() 开始数据流,因此我删除了 .pause() 和 .resume() 并且没有发现任何问题.
  • 可能是一个关于旧主题的愚蠢问题,但是当您流式传输文件时,这些块存储在应用程序的内存中并在它们流式传输到 GCS 时被销毁?我只是想想象这将如何影响我的应用程序的内存需求。谢谢!

标签: node.js google-cloud-storage google-compute-engine restify


【解决方案1】:

您不能使用原始的req 流,因为它会产生整个请求正文,它是多部分的。您需要使用 multiparty 之类的内容解析请求,为您提供可读的蒸汽和所需的所有元数据。

【讨论】:

  • 这仅仅是因为我使用 CURL 的方式是模拟表单提交吗?如果是这样,是否有另一种不需要多方通过 curl 进行 POST 的方式?
  • 试试--data-binary标志,它应该按原样发送文件的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-18
  • 2016-12-20
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
  • 2017-04-12
  • 2021-06-09
相关资源
最近更新 更多