Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用强大的和(knox或aws sdk)将文件流式上载到Node.js上的S3_Node.js_Amazon S3_Formidable_Knox Amazon S3 Client - Fatal编程技术网

使用强大的和(knox或aws sdk)将文件流式上载到Node.js上的S3

使用强大的和(knox或aws sdk)将文件流式上载到Node.js上的S3,node.js,amazon-s3,formidable,knox-amazon-s3-client,Node.js,Amazon S3,Formidable,Knox Amazon S3 Client,我正在尝试使用或将通过表单提交的文件直接流式上载到AmazonS3存储桶。表单处理是用 我的问题是:如何正确地使用aws sdk(或knox)和这些库的最新特性来处理流 我知道这里已经有人以不同的方式问过这个话题,即: (这是关于overiding form.onPart()的非常有用的公认答案) 但是,我认为答案有点过时和/或离题(即CORS支持,出于各种原因,我现在不想使用它)和/或,最重要的是,没有提及aws sdk(请参阅:)或knox(特别是putStream()或其reada

我正在尝试使用或将通过表单提交的文件直接流式上载到AmazonS3存储桶。表单处理是用

我的问题是:如何正确地使用aws sdk(或knox)和这些库的最新特性来处理流

我知道这里已经有人以不同的方式问过这个话题,即:

  • (这是关于overiding form.onPart()的非常有用的公认答案)
但是,我认为答案有点过时和/或离题(即CORS支持,出于各种原因,我现在不想使用它)和/或,最重要的是,没有提及aws sdk(请参阅:)或knox(特别是putStream()或其readableStream.pipe(req)变体)的最新功能

经过几个小时的挣扎,我得出结论,我需要一些帮助(免责声明:我是一个相当新的流)

HTML格式:

<form action="/uploadPicture" method="post" enctype="multipart/form-data">
  <input name="picture" type="file" accept="image/*">
  <input type="submit">
</form>
请求后处理程序:

uploadPicture = (req, res, next) ->
  form = new formidable.IncomingForm()
  form.parse(req)

  form.onPart = (part) ->
    if not part.filename
      # Let formidable handle all non-file parts (fields)
      form.handlePart(part)
    else
      handlePart(part, form.bytesExpected)

  handlePart = (part, fileSize) ->
    # aws-sdk version
    params =
      Bucket: "mybucket"
      Key: part.filename
      ContentLength: fileSize
      Body: part # passing stream object as body parameter

    awsS3client.putObject(params, (err, data) ->
      if err
        console.log err
      else
        console.log data
    )
但是,我得到了以下错误:

{[RequestTimeout:您与服务器的套接字连接在超时期间未被读取或写入。空闲连接将被关闭。]

消息:“您与服务器的套接字连接在超时期间未被读取或写入。空闲连接将被关闭。”, 代码:“请求超时”, 名称:“请求超时”, 状态代码:400, 可检索:false}

以这种方式定制的handlePart()函数的knox版本也会失败:

handlePart = (part, fileSize) ->
  headers =
    "Content-Length": fileSize
    "Content-Type": part.mime
  knoxS3client.putStream(part, part.filename, headers, (err, res) ->
    if err
      console.log err
    else
      console.log res
  )      
我还得到一个有400个状态码的大res对象

在这两种情况下,区域都配置为eu-west-1

补充说明:

节点0.10.12

npm的最新版本(1.0.14)

来自npm的最新aws sdk(1.3.1)

npm的最新knox(0.8.3)

直接流式传输到Amazon S3是不可能的:

S3API要求您在创建新文件时提供其大小。在完全接收多部分/表单数据文件之前,此信息不适用于多部分/表单数据文件。这意味着流媒体是不可能的

实际上,form.bytesExpected指的是整个表单的大小,而不是单个文件的大小


因此,在上传到S3之前,数据必须首先到达服务器上的内存或磁盘。

使用AWS S3的多端口(作为工作模块)和node Foremble,您可以通过管道将流上传,如下所示:

var-nervouse=require('nervouse');
var http=require('http');
var util=require('util');
var AWS=要求('AWS-sdk');
var config=require('./config');
var s3=新的AWS.s3({
accessKeyId:config.get('S3\u ACCESS\u KEY'),
secretAccessKey:config.get('S3\u SECRET\u KEY'),
apiVersion:‘2006-03-01’
});
var s3Stream=require('s3-upload-stream')(s3);
var bucket=‘bucket name’;
var key='abcdefgh';
http.createServer(函数(req,res){
if(req.url=='/upload'&&req.method.toLowerCase()=='post'){
var form=new.IncomingForm();
表单.on('progress',函数(bytesReceived,bytesExpected){
//log('onprogress',parseInt(100*bytesReceived/bytesExpected),'%”);
});
表单.on('error',函数(err){
console.log('err',err);
});
//此“结束”用于客户端完成上载
//upload.on('uploaded')是指上传时
//在AWS S3上完成
关于('end',function()的表单{
log('end!!!!',参数);
});
在('aborted',function()上的表单{
log('aborted',参数);
});
form.onPart=函数(part){
console.log(“部分”,部分);
//部分看起来像这样
//    {
//可读性:对,
//标题:
//        {
//“内容处置”:“表单数据;name=“上传”;filename=“00video38.mp4”,
//“内容类型”:“视频/mp4”
//        },
//名称:“上传”,
//文件名:“00video38.mp4”,
//mime:“视频/mp4”,
//Transferencode:'二进制',
//传输缓冲区:“”
//    }
var start=new Date().getTime();
var upload=s3Stream.upload({
“桶”:桶,
“Key”:part.filename
});
//可选配置
//upload.maxPartSize(20971520);//20MB
上传。concurrentParts(5);
//处理错误。
upload.on('error',函数(error){
console.log('errr',error);
});
upload.on('part',函数(详细信息){
console.log(“部分”,详细信息);
});
upload.on('upload',函数(详细信息){
var end=new Date().getTime();
log('it take',end start);
console.log(“已上载”,详细信息);
});
//也许你可以像这样加上压缩
//part.pipe(压缩).pipe(上载)
管道部分(上传);
};
解析(请求、函数(错误、字段、文件){
res.writeHead(200,{'content-type':'text/plain'});
res.write('收到的上载:\n\n');
res.end(util.inspect({fields:fields,files:files}));
});
返回;
}
//显示文件上传表单
res.writeHead(200,{'content-type':'text/html'});
res.end(
''+
“
”+ “
”+ ''+ '' ); }).听(8080);
因为这篇文章太老了,我相信现在支持直接流媒体,所以我花了很多时间阅读关于这个主题的过时答案

如果它对任何人都有帮助的话,我可以直接从客户机流式传输到s3,而无需任何必要
handlePart = (part, fileSize) ->
  headers =
    "Content-Length": fileSize
    "Content-Type": part.mime
  knoxS3client.putStream(part, part.filename, headers, (err, res) ->
    if err
      console.log err
    else
      console.log res
  )      
var formidable = require('formidable');
var http = require('http');
var util = require('util');
var AWS      = require('aws-sdk');
var config = require('./config');
var s3 = new AWS.S3({
    accessKeyId: config.get('S3_ACCESS_KEY'),
    secretAccessKey: config.get('S3_SECRET_KEY'),
    apiVersion: '2006-03-01'
});
var s3Stream = require('s3-upload-stream')(s3);
var bucket = 'bucket-name';
var key = 'abcdefgh';


http.createServer(function(req, res) {

    if (req.url == '/upload' && req.method.toLowerCase() == 'post') {

        var form = new formidable.IncomingForm();
        form.on('progress', function(bytesReceived, bytesExpected) {
            //console.log('onprogress', parseInt( 100 * bytesReceived / bytesExpected ), '%');
        });

        form.on('error', function(err) {
            console.log('err',err);
        });

        // This 'end' is for the client to finish uploading
        // upload.on('uploaded') is when the uploading is
        // done on AWS S3
        form.on('end', function() {
            console.log('ended!!!!', arguments);
        });

        form.on('aborted', function() {
            console.log('aborted', arguments);
        });

        form.onPart = function(part) {
            console.log('part',part);
            // part looks like this
            //    {
            //        readable: true,
            //        headers:
            //        {
            //            'content-disposition': 'form-data; name="upload"; filename="00video38.mp4"',
            //            'content-type': 'video/mp4'
            //        },
            //        name: 'upload',
            //            filename: '00video38.mp4',
            //        mime: 'video/mp4',
            //        transferEncoding: 'binary',
            //        transferBuffer: ''
            //    }

            var start = new Date().getTime();
            var upload = s3Stream.upload({
                "Bucket": bucket,
                "Key": part.filename
            });

            // Optional configuration
            //upload.maxPartSize(20971520); // 20 MB
            upload.concurrentParts(5);

            // Handle errors.
            upload.on('error', function (error) {
                console.log('errr',error);
            });
            upload.on('part', function (details) {
                console.log('part',details);
            });
            upload.on('uploaded', function (details) {
                var end = new Date().getTime();
                console.log('it took',end-start);
                console.log('uploaded',details);
            });

            // Maybe you could add compress like
            // part.pipe(compress).pipe(upload)
            part.pipe(upload);
        };

        form.parse(req, function(err, fields, files) {
            res.writeHead(200, {'content-type': 'text/plain'});
            res.write('received upload:\n\n');
            res.end(util.inspect({fields: fields, files: files}));
        });
        return;
    }

    // show a file upload form
    res.writeHead(200, {'content-type': 'text/html'});
    res.end(
        '<form action="/upload" enctype="multipart/form-data" method="post">'+
        '<input type="text" name="title"><br>'+
        '<input type="file" name="upload" multiple="multiple"><br>'+
        '<input type="submit" value="Upload">'+
        '</form>'
    );
}).listen(8080);
const fileUploadStream = (req, res) => {
  //get "body" args from header
  const { id, fn } = JSON.parse(req.get('body'));
  const Key = id + '/' + fn; //upload to s3 folder "id" with filename === fn
  const params = {
    Key,
    Bucket: bucketName, //set somewhere
    Body: req, //req is a stream
  };
  s3.upload(params, (err, data) => {
    if (err) {
      res.send('Error Uploading Data: ' + JSON.stringify(err) + '\n' + JSON.stringify(err.stack));
    } else {
      res.send(Key);
    }
  });
};
...
  const params = {
      Key,
      Bucket: bucketName,
      Body: req,
      ContentType: 'image/jpg'
  };
  s3.upload(params, (err, data) => {
      if (err) return err;
      console.log(data);
  });
...