13

使用 Express 和 Node,我可以成功上传文件并将其传递到以下代码块中的 Azure 存储。

app.get('/upload', function (req, res) {
    res.send(
    '<form action="/upload" method="post" enctype="multipart/form-data">' +
    '<input type="file" name="snapshot" />' +
    '<input type="submit" value="Upload" />' +
    '</form>'
    );
});

app.post('/upload', function (req, res) {
    var path = req.files.snapshot.path;
    var bs= azure.createBlobService();
    bs.createBlockBlobFromFile('c', 'test.png', path, function (error) { });
    res.send("OK");
});

这工作得很好,但 Express 创建了一个临时文件并首先存储图像,然后我从文件将其上传到 Azure。这似乎是该过程中效率低下且不必要的步骤,我最终不得不管理临时文件目录的清理。

我应该能够使用blobService.createBlockBlobFromStreamAzure SDK 中的方法将文件直接流式传输到 Azure 存储,但我对 Node 或 Express 不够熟悉,无法理解如何访问流数据。

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

    var stream = /// WHAT GOES HERE ?? ///

    var bs= azure.createBlobService();
    bs.createBlockBlobFromStream('c', 'test.png', stream, function (error) { });
    res.send("OK");
});

我发现以下博客表明可能有一种方法可以做到这一点,当然 Express 正在抓取流数据并解析并将其保存到文件系统中。http://blog.valeryjacobs.com/index.php/streaming-media-from-url-to-blob-storage/

vjacobs 代码实际上是从另一个站点下载文件并将该流传递到 Azure,所以我不确定它是否可以适应我的情况。

如何使用 Node 访问上传的文件流并将其直接传递到 Azure?

4

4 回答 4

18

解决方案(基于与@danielepolencic 的讨论)

使用 Multiparty(npm install multiparty),一个 Formidable 的分支,如果我们禁用 Express 的 bodyparser() 中间件,我们可以访问多部分数据(有关更多信息,请参阅他们的注释)。与 Formidable 不同,Multiparty 不会将文件流式传输到磁盘,除非您告诉它这样做。

app.post('/upload', function (req, res) {
    var blobService = azure.createBlobService();
    var form = new multiparty.Form();
    form.on('part', function(part) {
        if (part.filename) {

            var size = part.byteCount - part.byteOffset;
            var name = part.filename;

            blobService.createBlockBlobFromStream('c', name, part, size, function(error) {
                if (error) {
                    res.send({ Grrr: error });
                }
            });
        } else {
            form.handlePart(part);
        }
    });
    form.parse(req);
    res.send('OK');
});

支持@danielepolencic 帮助找到解决方案。

于 2013-08-22T15:30:04.903 回答
9

正如您从连接中间件文档中看到的那样,它会bodyparser自动为您处理表单。在您的特定情况下,它解析传入的多部分数据并将其存储在其他地方,然后以一种很好的格式(即req.files)公开保存的文件。

不幸的是,我们不需要(也不需要)黑魔法,主要是因为我们希望能够将传入的数据直接流式传输到 azure 而不会撞到磁盘(即req.pipe(res))。因此,我们可以关闭bodyparser中间件,自己处理传入的请求。在后台,bodyparser使用node-formidable,因此在我们的实现中重用它可能是一个好主意。

var express = require('express');
var formidable = require('formidable');
var app = express();

// app.use(express.bodyParser({ uploadDir: 'temp' }));

app.get('/', function(req, res){
  res.send('hello world');
});

app.get('/upload', function (req, res) {
    res.send(
    '<form action="/upload" method="post" enctype="multipart/form-data">' +
    '<input type="file" name="snapshot" />' +
    '<input type="submit" value="Upload" />' +
    '</form>'
    );
});

app.post('/upload', function (req, res) {
  var bs = azure.createBlobService();
  var form = new formidable.IncomingForm();
  form.onPart = function(part){
    bs.createBlockBlobFromStream('taskcontainer', 'task1', part, 11, function(error){
      if(!error){
          // Blob uploaded
      }
    });
  };
  form.parse(req);
  res.send('OK');
});

app.listen(3000);

核心思想是我们可以利用节点流,这样我们就不需要在将完整文件发送到 azure 之前将其加载到内存中,但我们可以在它出现时传输它。强大的节点模块支持流,因此将流管道传输到 azure 将实现我们的目标。

post您可以轻松地在本地测试代码,而无需通过将路由替换为 azure :

app.post('/upload', function (req, res) {
  var form = new formidable.IncomingForm();
    form.onPart = function(part){
      part.pipe(res);
    };
    form.parse(req);
});

在这里,我们只是将请求从输入传送到输出。bodyParser 您可以在此处阅读更多信息。

于 2013-08-21T19:40:50.510 回答
1

通过 Azure Storage SDK for Node 上传二进制数据(例如图像)有不同的选项,而不是使用多部分。

基于 Node 中的 Buffer 和 Stream 定义并对其进行操作,这些可以使用几乎所有的 BLOB 上传方法来处理:createWriteStreamToBlockBlob, createBlockBlobFromStream, createBlockBlobFromText.

可以在此处找到参考:将二进制数据从请求正文上传到 Node.js 中的 Azure BLOB 存储 [restify]

于 2015-09-16T14:50:48.893 回答
0

尝试实施解决方案时遇到 .createBlockBlobFromStream 问题的人,请注意,此方法在较新版本中略有更改

旧版:

createBlockBlobFromStream(containerName, blobName, part, size, callback)

新版本

createBlockBlobFromStream(containerName, blobName, part, size, options, callback)

(如果您不关心选项,请尝试使用空数组)作为参数。

奇怪的是,“选项”应该是可选的,但无论出于何种原因,如果我忽略它,我的会失败。

于 2013-11-11T04:55:21.693 回答