当前位置: 首页 > 面试题库 >

使用NodeJS将文件上传到Amazon S3

吕钧
2023-03-14
问题内容

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

这些是我的路线设置:

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

这是items.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');
            }
        });
    });
};

Bodyparam
设置为类似字符串的"hello"效果很好。根据doc,Bodyparam必须获取 (缓冲区,类型数组,Blob,字符串,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' }

任何帮助将不胜感激!


问题答案:

因此,看来这里有些问题。根据您的帖子,您似乎正在尝试使用connect- multiparty中间件支持文件上传。该中间件所做的是获取上载的文件,将其写入本地文件系统,然后设置req.files为上载的文件。

您的路由配置看起来不错,问题似乎出在您的items.upload()功能上。特别是这部分:

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

正如我在答案开头提到的那样,connect- multiparty将文件写入本地文件系统,因此您需要打开文件并读取它,然后将其上传,然后在本地文件系统上将其删除。

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

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.JS中本机FS相似的接口,但抽象了一些细节,例如分段上传和S3
api (以及添加一些其他功能,例如递归方法)。

如果要拉入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();
    });
};

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

如果愿意,可以将代码更改为Promises的回调。或将pipe()方法与事件侦听器一起使用来确定结束/错误。

如果您正在寻找其他方法,请查看s3fs的文档,如果您正在寻找其他方法或遇到问题,请随时提出问题。



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

  • 我正在使用lambda nodejs将文件上传到ftp服务器。 上传文件的源代码: index.js文件: 运行后的日志: 回应: 零 请求ID: “9c8e1701-ad54-42eb-8dc6-bbed77bc9b41” 函数日志: 开始请求id:9c8e 1701-ad54-42e b-8dc 6-bbed 77 BC 9 b 41版本:$最新 结束请求ID:9c8e1701-ad54-42

  • 我正在尝试用我的服务帐户在我的机器上本地使用简单的代码上传一个图片到Google云存储: 然而,我得到了下面的错误消息。是Google Cloud API只能在部署到App Engine上时工作,还是我在这里做错了什么?我能够使用相同的服务帐户使Google Vision API在本地工作。

  • 我在尝试将文件上传到我的S3存储桶时遇到了问题。一切正常,除了我的文件参数似乎不合适。我正在使用Amazon S3 sdk从nodejs上传到s3。 以下是我的路线设置: 这是个项目。upload()函数: 将“Body”参数设置为类似“hello”的字符串可以正常工作。根据doc,Body必须获取(Buffer、类型化数组、Blob、String、ReadableStream)对象数据。但是,上

  • 本文向大家介绍NodeJS使用formidable实现文件上传,包括了NodeJS使用formidable实现文件上传的使用技巧和注意事项,需要的朋友参考一下 最近自学了一下NodeJS,然后做了一个小demo,实现歌曲的添加、修改、播放和删除的功能,其中自然要实现音乐和图片的上传功能。于是上网查找资料,找到了一个formidable插件,该插件可以很好的实现文件的上传功能。该小demo用到了My

  • 问题内容: 谁能告诉我如何使用nodejs和HAPI上传文件? 我在处理程序中获取二进制数据。 这是我的html代码: 这是我的Nodejs代码: 问题答案: 最后,我得到了使用HAPI上传大型文件的解决方案,并感谢Roman。 解决方法如下: server.js代码 处理程序代码: