node.js - 如何从 POST 正文获取 wav 文件并使用 Node JS/Express 上传

标签 node.js express multer

我正在创建一个 Node js 应用程序,其目的部分是接收 POST 请求,然后解析正文以获取 2 个字段:id 和 .wav 文件。

不幸的是,我似乎无法正确解析请求主体。我相信请求应该是 multipart/form-data (这就是我使用 multer 而不是 bodyParser 的原因),但是当我尝试 log(body.req.file) 时,我一直未定义,并且 res 显示我在 app.post 函数中发送的 500 内部服务器错误。

这是服务器代码...

穆特部分:

var upload = multer({ storage: storage })
var uploadFields = upload.fields([{name: 'id'}, {name: 'file'}])

var storage = multer.diskStorage({
    destination: function(req, file, cb){
        cb(null, 'temp/')
    },
    filename: function(req, file, cb){
        fileBody = file
        keyName = `${req.body.id}.` + getExtension(file)
        var objectParams = {Bucket: myBucket, Key: keyName, Body: fileBody}
        s3.putObject(objectParams).promise().then(function(res){console.log('wewlad')}).catch(function(err){console.log(err)})
        cb(null, file.fieldname + '-' + Date.now() + '.' + getExtension(file))
    }
})

表达部分:

app.post('/', uploadFields, function(req, res){
    console.log('POST to / recieved!')
    console.log(req.body.id)
    console.log(req.body.file)  

    fileBody = req.files
    keyName = req.body.id + '.wav'
    var params = {Bucket: myBucket, Key: keyName, Body: fileBody}
    var putObjectPromise = s3.putObject(params).promise()
    putObjectPromise.then(function(res){
        console.log(res)

    }).catch(function(err){
        console.log(err)
    })
})

我制作的 getExtension 函数(不确定是否需要)...

function getExtension(file) {
    var res = ''
    //some of these are being used for testing
    if (file.mimetype === 'audio/wav') res = '.wav'
    else if (file.mimetype === 'audio/basic') res = '.ul'
    else if (file.mimetype === 'multipart/form-data') res = '.wav'
    else if (file.mimetype === 'application/octet-stream') res = '.ul'
    else console.log(`ERROR: ${file.mimetype} is not supported by this application!`)
    return res
}

旁注:我正在使用 post-man 将 id 和文件作为表单数据发送

非常感谢任何帮助!另外,如果我遗漏了什么,请告诉我!

编辑: 使用新信息再次尝试,这是我的尝试:

 var upload = multer({ dest: 'uploads/' }) //what do I put here to not store file
 ...
 ...
 app.post('/', upload.single('file'), function(req, res, next){
    console.log('POST to / received!')
    console.log(req.body.id)
    console.log(req.file)

    var fileBody = req.file //and what do I put here to get access to the file
    var keyName = `audio-${req.body.id}.${getExtension(req.file)}`
    var params = { Bucket: myBucket, Key: keyName, Body: fileBody }
    var putObjectPromise = s3.putObject(params).promise()

    putObjectPromise.then(function(res){
        console.log(res)
        res.sendStatus(204);
    }).catch(err =>{
        console.log(err)
        next(err)
    })
});

它会产生“InvalidParameterType:预期 params.Body 为字符串、缓冲区、流、blob 或类型化数组对象”,我来自 S3,验证 putObject 调用的参数

给 future 路过的人的解决方案:

 var upload = multer()


app.post('/', upload.single('file'), function(req, res, next){
    //for debugging purposes
    console.log('POST to / received!')
    console.log(req.body.id)
    console.log(req.file)

    //set the parameters for uploading the files to s3
    var fileBody = req.file.buffer
    var keyName = `audio_logs/audio-${req.body.id}.${getExtension(req.file)}`
    var params = { Bucket: myBucket, Key: keyName, Body: fileBody }

    //upload the audio file and then state when done. Log any errors.
    var putObjectPromise = s3.putObject(params).promise()
    putObjectPromise.then(function(res){
        console.log('Uploaded -> ' + res)        
    }).catch(err =>{
        console.log(err)
        next(err)
    })
});

最佳答案

正如 @shortstuffsushi 所指出的,由于您使用的是 multer.fields,文件元数据被解析为 req.files

但是,该对象不是实际的文件正文。 它是一个键->值映射,其中每个键都是您在 multer.fields 中定义的字段之一,每个值都是一个文件对象数组

因此,如果我正确读取您的代码,您将必须以 req.files['file'][0] 的形式访问您的文件。

此外,由于您将 multer 配置为使用 DiskStorage,因此该文件对象将不包含实际的文件正文。相反,它有一个 path 属性,指向文件系统上的文件。

因此,为了将其上传到 S3,您首先必须将其从磁盘读取到缓冲区或流中(取决于上传库可以使用的内容),然后使用它来实际上传文件的数据。

<小时/>

如果您每次请求仅上传一个文件,则应考虑使用 multer.single 而不是 multer.fields。我认为 id 字段是数字或字符串,因此在 multer.fields 中指定该字段只会使其尝试将无意义的内容解析到文件中。

使用multer.single,文件元数据将被解析为req.file(没有“s”),因此您不需要额外的“映射到数组”访问权限。

完整的示例如下所示:

const readFile = require('util').promisify(require('fs').readFile)

app.post('/', upload.single('file'), function(req, res, next){
    console.log('POST to / received!')
    console.log(req.body.id)
    console.log(req.file)  

    readFile(req.file.path)
      .then(body => {
        const params = { Bucket: myBucket, Key: req.body.id + '.wav', Body: body }
        return s3.putObject(params).promise();
      })
      .then(result => {
        console.log(result)
        res.sendStatus(204);
      })
      .catch(err => {
        console.error(err);
        next(err);
      });
});

正如 @shortstuffsushi 提到的,multer 的 filename 配置也不应该上传文件。

关于node.js - 如何从 POST 正文获取 wav 文件并使用 Node JS/Express 上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51662622/

相关文章:

node.js - NodeJS Sequelize - 启动应用程序时出错

javascript - 以 Express 方式发送上传的图像

node.js - 如何使用 Express/Nodejs 缓存单个资源

node.js - fs.unlink 不会删除文件

javascript - MongoDB/ExpressJS -- 当 ObjectID 包含在变量中时,通过 _id 删除文档

javascript - 为什么要使用 ng-file-upload 上传服务

javascript - NodeJS Multer 不工作

javascript - ffmpeg 仅将我的 41.25% 的图像转换为视频

javascript - 无法使用 Express 和 Mongoose 存储新用户

node.js - Ghost安装成功后出现403 Forbidden