So I've been using LoopbackJS for the past 2-3 months and I'm currently building a file uploader (specifically for profile avatar image). But every time I sent an image file to the endpoint it never received by the server and tagged it as "undefined" which breaks the process. Can anyone help me identify what is wrong with my code?
Here are my codes currently.
file-upload.controller.ts
@post('/files', {
responses: {
'204': {
description: 'Uploaded',
},
},
})
async fileUpload(
@requestBody.file()
request: Request,
@inject(RestBindings.Http.RESPONSE) response: Response,
): Promise<string> {
console.log(request.file.filename);
const storage = multer.diskStorage({
destination: './public/uploads',
filename: function (req, file, cb) {
cb(null, 'image-' + Date.now() + path.extname(file.filename));
},
});
const upload = multer({storage: storage}).single('image');
upload(request, response, (err: unknown) => {
if (err) console.log(err);
else {
console.log(request.file.filename);
}
});
return 'Yes';
}
For anyone asking, I used the console.log(request.file.filename)
to debug whether the request actually bring the file or not.
Here's my request using Postman
Error Log
Unhandled error in POST /files: 500 TypeError: Cannot read property 'filename' of undefined
at FileUploadController.fileUpload (D:\Project\API\carena-api\src\controllers\file-upload.controller.ts:42:30)
at invokeTargetMethod (D:\Project\API\carena-api\node_modules\@loopback\context\src\invocation.ts:255:47)
at D:\Project\API\carena-api\node_modules\@loopback\context\src\invocation.ts:232:12
at Object.transformValueOrPromise (D:\Project\API\carena-api\node_modules\@loopback\context\src\value-promise.ts:298:12)
at invokeTargetMethodWithInjection (D:\Project\API\carena-api\node_modules\@loopback\context\src\invocation.ts:227:10)
at InterceptedInvocationContext.invokeTargetMethod (D:\Project\API\carena-api\node_modules\@loopback\context\src\invocation.ts:118:14)
at targetMethodInvoker (D:\Project\API\carena-api\node_modules\@loopback\context\src\interceptor.ts:349:23)
at D:\Project\API\carena-api\node_modules\@loopback\context\src\interceptor-chain.ts:218:14
at Object.transformValueOrPromise (D:\Project\API\carena-api\node_modules\@loopback\context\src\value-promise.ts:298:12)
at GenericInterceptorChain.invokeNextInterceptor (D:\Project\API\carena-api\node_modules\@loopback\context\src\interceptor-chain.ts:213:12)
at GenericInterceptorChain.next (D:\Project\API\carena-api\node_modules\@loopback\context\src\interceptor-chain.ts:201:17)
at GenericInterceptorChain.invokeInterceptors (D:\Project\API\carena-api\node_modules\@loopback\context\src\interceptor-chain.ts:178:17)
at Object.invokeInterceptors (D:\Project\API\carena-api\node_modules\@loopback\context\src\interceptor-chain.ts:250:16)
at D:\Project\API\carena-api\node_modules\@loopback\context\src\interceptor.ts:351:14
at tryCatchFinally (D:\Project\API\carena-api\node_modules\@loopback\context\src\value-promise.ts:222:14)
at Object.tryWithFinally (D:\Project\API\carena-api\node_modules\@loopback\context\src\value-promise.ts:197:10)
Thank you.
The console log at the top of the code cause the error. You should verify the error with line number. The debug mode in any IDE is helpful to figure out what went wrong. Here is the corrected code
@post('/files')
async fileUpload(
@requestBody({
content: {
'multipart/form-data': {
'x-parser': 'stream',
schema: {type: 'object'},
},
},
})
request: Request,
@inject(RestBindings.Http.RESPONSE) response: Response,
): Promise<string> {
const storage = multer.memoryStorage();
const upload = multer({storage});
const fileArr = await new Promise<any[]>((resolve, reject) => {
upload.any()(<any>request, <any>response, err => {
if (err) reject(err);
else {
resolve(<any[]>request.files);
}
});
});
console.log(fileArr[0].originalname);
....
....
....
return 'Yes';
}
Use fileArr[0].buffer
to write file to the disk