我正在构建一个节点api,它能够处理多部分文件类型(块)的上传。此api基于Fastify库,并且我已经安装了单独的Fastify-Multipart库。我已经做好了所有的工作,包括多部分文件上传,但是这个api的部分要求是能够向另一个api发送请求。特别是,我需要发送文件上传。我不知道他们的api是用什么写的,但他们的分片文件上传api基本上是这样的:
sdk.files.uploader(location_id, file_size, "filename.jpg", file)
.then(uploader => uploader.start())
.then(file => { console.log(file) })我的代码基本上是这样的:
post: async (request, reply) => {
// Check for file upload
if((request.headers['content-type'] && request.headers['content-type'].indexOf('multipart/form-data') !== -1) && request.params.id) {
const multipart = request.multipart(async (field, stream, filename, encoding, mimetype) => {
console.log(`folderId: ${request.params.id} filename: ${filename},
field name: ${field}, encoding: ${encoding},
mime type: ${mimetype}, file length: ${request.headers['content-length']}`)
try {
let uploader = await sdk.files.uploader(request.params.id, Number(request.headers['content-length']), filename, stream)
let file = await uploader.start()
console.log(file) //Never reaches this point
}
catch(e) {
console.log(`An error occurred during upload: ${e.message}`)
reply.code(500).send()
}
//pump(file, fs.createWriteStream(filename))
}, (error) => {
if(error) {
console.log(`Error uploading file: ${error.message}`)
reply.code(500).send()
} else {
console.log('File upload succeeded') //Upload succeeds but it's just in memory
reply.code(201).send()
}
})
multipart.on('field', (key, value) => {
console.log('form-data', key, value)
})
}
}所以基本上我想要做的就是传递一个多部分的文件流给第三方api,但是这样做似乎行不通(当我访问他们的网站时,我看不到文件夹中的文件)。当我查看机器上的活动监视器(macOS)时,我发现节点进程消耗了1.2G的内存(大致相当于文件的大小)。有谁知道如何使用Fastify-Multipart (我相信它是基于BusBoy的)来做到这一点。
发布于 2020-01-30 16:17:08
我注意到您的处理程序post: async (request, reply) =>是异步的,但是您没有调用await,而是在多部分回调中管理reply。这可能会导致问题。Read the promise resolution doc获取详细信息。
我建议检查通过管道传输流的模块,因为它必须使用steam方法,而不是将所有块保存到内存中。
下面是一个简单的例子:
const fastify = require('fastify')({ logger: true })
const pump = require('pump')
fastify.register(require('fastify-multipart'))
fastify.post('/', function (req, reply) { // this function must not be async
if (!req.isMultipart()) { // you can use this decorator instead of checking headers
reply.code(400).send(new Error('Request is not multipart'))
return
}
const mp = req.multipart(handler, onEnd)
mp.on('field', function (key, value) {
console.log('form-data', key, value)
})
function onEnd (err) {
if (err) {
reply.send(err)
return
}
console.log('upload completed')
reply.code(200).send()
}
async function handler (field, file, filename, encoding, mimetype) {
console.log('.....waiting')
await wait() // testing async function
pump(file, ConsoleWriter({ highWaterMark: 1000 }))
}
})
fastify.listen(3000)
function wait () {
return new Promise(resolve => {
setTimeout(resolve, 1000)
})
}
// A writer that manage the bytes
const { Writable } = require('stream')
function ConsoleWriter (opts) {
return new Writable({
...opts,
write (chunk, encoding, done) {
console.log({ chunk: chunk.length, encoding })
setTimeout(done, 500) // slow simulation
}
})
}调用它时使用:
curl -F file=@"./README.md" -H 'content-type: multipart/form-data' -X POST http://localhost:3000/https://stackoverflow.com/questions/59937942
复制相似问题