How to wait for the result of writeHandler in a formidable file upload request?
itinance opened this issue · comments
I want to use formidable to upload files directly to S3. Following the official example it works just fine. However, I want to await the upload process and return the final URL of the uploaded file inside of the Http-Request to my client. And this seems to be a a challenge due to the limited nature of how fileWriteStreamHandler
needs to be typed.:
const s3Client = new AWS.S3({
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_KEY,
},
});
const uploadStream = (file) => {
const pass = new PassThrough();
s3Client.upload(
{
Bucket: 'demo-bucket',
Key: file.newFilename,
Body: pass,
},
(err, data) => {
console.log(err, data);
},
);
return pass;
};
const server = http.createServer((req, res) => {
if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
// parse a file upload
const form = formidable({
fileWriteStreamHandler: uploadStream,
});
form.parse(req, () => {
res.writeHead(200);
res.end();
});
return;
}
form.parse
returns immediately, no matter how long the S3-upload process works under the hood.
I tried to use a promise
and await
but the function type of uploadStream
must not return a promise.
Type '(file: any) => Promise<any>' is not assignable to type '(file?: VolatileFile | undefined) => Writable'.
I want to achieve something like that:
form.parse(req, (uploadedFile: string) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ url: uploadedFile }, null, 2));
res.end();
});
In order to do that, I need something like a return value from the uploadStream
function where I would be able to receive the final information eventually. But since it is only returning a PassThrough
-object, it seems to be very limited in that case for further approaches like mine.
Do you guys know how I can do that?
Have you tried to res.end inside the s3Client.upload callback (you need to have a ref to res there)