当前位置: 首页 > 知识库问答 >
问题:

使用NodeJS将文件上载到Amazon S3

麻阳
2023-03-14

我在尝试将文件上传到我的S3存储桶时遇到了问题。一切正常,除了我的文件参数似乎不合适。我正在使用Amazon S3 sdk从nodejs上传到s3。

以下是我的路线设置:

var multiparty = require('connect-multiparty'),
    multipartyMiddleware = multiparty();
app.route('/api/items/upload').post(multipartyMiddleware, items.upload);

这是个项目。upload()函数:

exports.upload = function(req, res) {
    var file = req.files.file;
    var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}});
    s3bucket.createBucket(function() {
        var params = {
            Key: file.name,
            Body: file
        };
        s3bucket.upload(params, function(err, data) {
            console.log("PRINT FILE:", file);
            if (err) {
                console.log('ERROR MSG: ', err);
            } else {
                console.log('Successfully uploaded data');
            }
        });
    });
};

将“Body”参数设置为类似“hello”的字符串可以正常工作。根据doc,Body必须获取(Buffer、类型化数组、Blob、String、ReadableStream)对象数据。但是,上载文件对象失败,并显示以下错误消息:

[Error: Unsupported body payload object]

这是文件对象:

{ fieldName: 'file',
  originalFilename: 'second_fnp.png',
  path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png',
  headers: 
   { 'content-disposition': 'form-data; name="file"; filename="second_fnp.png"',
     'content-type': 'image/png' },
  ws: 
   { _writableState: 
      { highWaterMark: 16384,
        objectMode: false,
        needDrain: true,
        ending: true,
        ended: true,
        finished: true,
        decodeStrings: true,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function],
        writecb: null,
        writelen: 0,
        buffer: [],
        errorEmitted: false },
     writable: true,
     domain: null,
     _events: { error: [Object], close: [Object] },
     _maxListeners: 10,
     path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png',
     fd: null,
     flags: 'w',
     mode: 438,
     start: undefined,
     pos: undefined,
     bytesWritten: 261937,
     closed: true },
  size: 261937,
  name: 'second_fnp.png',
  type: 'image/png' }

任何帮助都将不胜感激!

共有3个答案

陆仲渊
2023-03-14

或使用promise:

const AWS = require('aws-sdk');
AWS.config.update({
    accessKeyId: 'accessKeyId',
    secretAccessKey: 'secretAccessKey',
    region: 'region'
});

let params = {
    Bucket: "yourBucketName",
    Key: 'someUniqueKey',
    Body: 'someFile'
};
try {
    let uploadPromise = await new AWS.S3().putObject(params).promise();
    console.log("Successfully uploaded data to bucket");
} catch (e) {
    console.log("Error uploading data: ", e);
}
何超英
2023-03-14

我发现以下是一个有效的解决方案

npm install aws-sdk


安装aws-sdk后,使用以下代码将值替换为需要的值。

var AWS = require('aws-sdk');
var fs =  require('fs');

var s3 = new AWS.S3();

// Bucket names must be unique across all S3 users

var myBucket = 'njera';

var myKey = 'jpeg';
//for text file
//fs.readFile('demo.txt', function (err, data) {
//for Video file
//fs.readFile('demo.avi', function (err, data) {
//for image file                
fs.readFile('demo.jpg', function (err, data) {
  if (err) { throw err; }



     params = {Bucket: myBucket, Key: myKey, Body: data };

     s3.putObject(params, function(err, data) {

         if (err) {

             console.log(err)

         } else {

             console.log("Successfully uploaded data to myBucket/myKey");

         }

      });

});

我在这里找到了关于这个主题的完整教程,以备您查找参考资料::

亢保赫
2023-03-14

所以看起来这里有一些问题。根据您的帖子,看起来您正在尝试使用连接多方中间件支持文件上传。此中间件所做的是获取上传的文件,将其写入本地文件系统,然后将req.files设置为上传的文件。

路线的配置看起来很好,问题似乎出在您的项目上。upload()函数。特别是本部分:

var params = {
  Key: file.name,
  Body: file
};

正如我在回答开始时提到的那样,连接多方将文件写入本地文件系统,因此您需要打开文件并读取它,然后上载,然后在本地文件系统上删除它。

也就是说,您可以将方法更新为以下内容:

var fs = require('fs');
exports.upload = function (req, res) {
    var file = req.files.file;
    fs.readFile(file.path, function (err, data) {
        if (err) throw err; // Something went wrong!
        var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}});
        s3bucket.createBucket(function () {
            var params = {
                Key: file.originalFilename, //file.name doesn't exist as a property
                Body: data
            };
            s3bucket.upload(params, function (err, data) {
                // Whether there is an error or not, delete the temp file
                fs.unlink(file.path, function (err) {
                    if (err) {
                        console.error(err);
                    }
                    console.log('Temp File Delete');
                });

                console.log("PRINT FILE:", file);
                if (err) {
                    console.log('ERROR MSG: ', err);
                    res.status(500).send(err);
                } else {
                    console.log('Successfully uploaded data');
                    res.status(200).end();
                }
            });
        });
    });
};

这样做的目的是从本地文件系统读取上传的文件,然后将其上传到S3,然后删除临时文件并发送响应。

这种方法有几个问题。首先,它的效率不尽如人意,对于大文件,您将在写入之前加载整个文件。其次,此过程不支持大文件的多部分上传(我认为在您必须进行多部分上传之前,截止值为5 Mb)。

相反,我建议您使用我一直在开发的一个名为S3FS的模块,该模块提供了与Node中的本机FS类似的接口。JS,但抽象了一些细节,如多部分上传和S3API(以及添加了一些其他功能,如递归方法)。

如果您要拉入S3FS库,您的代码将如下所示:

var fs = require('fs'),
    S3FS = require('s3fs'),
    s3fsImpl = new S3FS('mybucketname', {
        accessKeyId: XXXXXXXXXXX,
        secretAccessKey: XXXXXXXXXXXXXXXXX
    });

// Create our bucket if it doesn't exist
s3fsImpl.create();

exports.upload = function (req, res) {
    var file = req.files.file;
    var stream = fs.createReadStream(file.path);
    return s3fsImpl.writeFile(file.originalFilename, stream).then(function () {
        fs.unlink(file.path, function (err) {
            if (err) {
                console.error(err);
            }
        });
        res.status(200).end();
    });
};

这将为提供的bucket和AWS凭据实例化模块,然后创建不存在的bucket。然后,当上传文件的请求通过时,我们将打开一个文件流,并使用它将文件写入S3到指定路径。这将在后台(如果需要)处理多部分上传,并且有通过流完成的好处,因此在开始上传之前,您不必等待读取整个文件。

如果您愿意,您可以将代码更改为Promises的回调。或者使用带有事件侦听器的管道()方法来确定结束/错误。

如果您正在寻找一些其他方法,请查看S3F的文档,如果您正在寻找一些其他方法或有问题,请随时提出问题。

 类似资料:
  • 问题内容: 尝试将文件上传到S3存储桶时遇到问题。一切正常,除了我的文件参数似乎不合适。我正在使用Amazon S3 SDK从Node.js上载到S3。 这些是我的路线设置: 这是items.upload()函数: 将param 设置为类似字符串的效果很好。根据doc,param必须获取 (缓冲区,类型数组,Blob,字符串,ReadableStream)对象数据。 但是,上传文件对象失败,并显示

  • 我的upload.js文件包含以下代码: 它通过终端工作,但我如何调用它在表单提交按钮点击或只是从不同的文件? 当我尝试的时候,它给我: 无法读取未定义的属性“prototype” 我对NodeJs还很陌生,我真的不知道该怎么做。 Google文档对我一点帮助都没有:/

  • 根据SkyDrive api(http://msdn.microsoft.com/en-us/library/live/hh826531.aspx#uploading_files),我在帖子请求的正文中以字节[]传递图像的内容。文件创建发生在skyDrive服务器上,但当我在skyDrive中打开它时,它说“文件应用程序被损坏或损坏”。 请求的正文 --A300x内容处理:表单数据;name=“f

  • 我尝试使用C#将文件上传到FTP服务器。文件已上传,但字节为零。

  • 我正在尝试上传一个文本文件(也尝试了PDF等)到Salesforce。文本文件包含“Hello World”。 这是我正在使用的代码 这将导致以下看起来符合Salesforce指导原则的请求正文:https://developer.Salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_bl

  • 这个问题非常类似于如何禁用ExpressBodyParser进行文件上传(Node.js)。他们提供的答案是针对Express3的,我用更新后的Express4尝试了这个解决方案,但它似乎不起作用。 我正在使用Node.jsExpress构建一个Web应用程序。我正在使用另一个库,BodyParser,来解析后参数。然而,我希望对多部分表单数据POSTS有更细粒度的访问——我需要将输入流管道到另一