如何从 POST 主体获取 wav 文件以使用节点 JS/Express 上传它
How to get a wav file from a POST body to upload it using Node JS/Express
我正在创建一个节点 js 应用程序,其部分目的是接收 POST 请求,然后解析 2 个字段的正文:id 和 .wav 文件。
不幸的是,我似乎无法正确解析请求正文。我相信请求应该是 multipart/form-data(这就是我使用 multer 而不是 bodyParser 的原因),但是当我尝试 log(body.req.file) 并且 res 显示 500 内部服务器时,我一直未定义我在 app.post 函数中发送的错误。
这是服务器代码...
多部分:
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: Expected params.Body to be a string, buffer, stream, blob, or typed array object" 我来自 S3 验证 putObject 调用的参数
以后路过的人解决办法:
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)
})
});
转换为第一个问题的答案,multer 在请求中使用 files
属性,而不是 body.file
。查看 their docs 了解更多。
正如@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'),因此您不需要额外的 "map into array" 访问权限。
所以完整的示例如下所示:
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 提到的,filename
multer 配置也不应该上传文件。
我正在创建一个节点 js 应用程序,其部分目的是接收 POST 请求,然后解析 2 个字段的正文:id 和 .wav 文件。
不幸的是,我似乎无法正确解析请求正文。我相信请求应该是 multipart/form-data(这就是我使用 multer 而不是 bodyParser 的原因),但是当我尝试 log(body.req.file) 并且 res 显示 500 内部服务器时,我一直未定义我在 app.post 函数中发送的错误。
这是服务器代码...
多部分:
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: Expected params.Body to be a string, buffer, stream, blob, or typed array object" 我来自 S3 验证 putObject 调用的参数
以后路过的人解决办法:
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)
})
});
转换为第一个问题的答案,multer 在请求中使用 files
属性,而不是 body.file
。查看 their docs 了解更多。
正如@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'),因此您不需要额外的 "map into array" 访问权限。
所以完整的示例如下所示:
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 提到的,filename
multer 配置也不应该上传文件。