routing-controllers icon indicating copy to clipboard operation
routing-controllers copied to clipboard

How to upload files with mutiple field with routing controller guys ?

Open Chanasit opened this issue 6 years ago • 15 comments

I looking to add a multiple file with multiple fields and its throw unexpected field.

Here this my code.

   @Post('/temple/upload')
    public uploadNewTemple(
        @Req() req: any,
        @Body() temple: TempleRequest,
        @UploadedFile( 'temple_cover_image' ) templeFile: Express.Multer.File,
        @UploadedFiles( 'photos' ) templePhotos: Array<Express.Multer.File>,
    ) {
        console.log(req)
        return []
    }

Thanks for you see this post.

Chanasit avatar Apr 15 '18 17:04 Chanasit

I am still getting stuck with uploading files. Although, i read the routing-controller guide-lines.

https://github.com/typestack/routing-controllers/issues/260

nguyentrunghieu3010 avatar Aug 13 '18 06:08 nguyentrunghieu3010

The problem is here: https://github.com/typestack/routing-controllers/blob/cb9a54cc72897252fc633be88c7f6be05c6be2cd/src/driver/express/ExpressDriver.ts#L131-L143

I think that routing-controllers should use multer.fields() to support this. Any PRs are welcome 😉

And as a workaround, I would recommend using multer manually:

@Post()
@UseBefore(multer.fields([{ name: 'one', maxCount: 1 }, { name: 'two', maxCount: 1 }]))
action(@Req() req: any) {
  const fileOne = req.files['one'][0];
  const fileTwo = req.files['two'][0];
}

MichalLytek avatar Aug 21 '18 07:08 MichalLytek

Stale issue message

github-actions[bot] avatar Feb 10 '20 00:02 github-actions[bot]

This shouldn't be closed. I encountered a similar issue today, it's not possible to have two separate @UploadedFile - in case we want to get them by field name explicitly.

feimosi avatar May 18 '20 19:05 feimosi

This shouldn't be closed. I encountered a similar issue today, it's not possible to have two separate @UploadedFile - in case we want to get them by field name explicitly.

Yeah had the same issue as well, multiple @UploadFile gives error

use this instead as pointed by @MichalLytek . One thing to note here is that, when you import multer its a function and not an object.

Adding example code down below

import multer from 'multer';
...
@Post('/upload')
@UseBefore(
    multer({ dest: 'uploads/' }).fields([
        { maxCount: 1, name: 'queryImage' },
        { maxCount: 1, name: 'referenceImage' },
    ]),
)
async handleImageUpload(@Req() req, @Res() res) {
    try {
        const allowedMimeTypes = ['image/jpeg'];

        const fileOne = req.files.queryImage[0];
        const fileTwo = req.files.referenceImage[0];

        if (!allowedMimeTypes.includes(fileOne.mimetype)) {
            throw new BadRequestError(`${fileTwo.mimetype} is not a supported file type!`);
        }

        // call your service here

        return ResponseUtil.ok({ data: { body: req.body, result } }, res);
    } catch (e) {
        return ResponseUtil.error(
            {
                code: 500,
                message: e.message,
                statusCode: 500
            },
            res,
        );
    }
}

Also, your request should look something like this Screenshot 2020-07-23 at 4 32 23 PM

shanurrahman-gcsns avatar Jul 23 '20 11:07 shanurrahman-gcsns

I'm having the same issue. I've attempted to use the approach given by @MichalLytek and @shanurrahman-gcsns but I'm getting TypeError: multer_1.default is not a function

DiefBell avatar Sep 23 '20 21:09 DiefBell

can you check if your type definitions are correct for your multer package, looks like you are trying a default export. try something like this import {something} from "sompackage"; instead of import something from "somepackage".

what version of node are you using? 14 ? The error is clear - your probably aren't using the same version of multer as I was.

shanurrahman-gcsns avatar Sep 24 '20 08:09 shanurrahman-gcsns

My multer version is 1.4.2. If you know what version you were on then I can probably downgrade. Running Node12 atm

DiefBell avatar Sep 24 '20 08:09 DiefBell

My multer version is 1.4.2. If you know what version you were on then I can probably downgrade. Running Node12 atm

I was also on multer 1.4.2. This should not have happened, and we dont have to use @types/multer with this version. I dont have an explanation for the issue you are facing right now.

multer_1.default this looks like you are compiling ts to js. In that case can you rebuild the project first. Or use ts-node to run the program and see if it gets resolved.

shanurrahman-gcsns avatar Sep 24 '20 08:09 shanurrahman-gcsns

I'm attempting both transpiling and running with ts-node, and have tried both Node 12 and 14. I'll give it a try without the multer typings

DiefBell avatar Sep 24 '20 09:09 DiefBell

I'm attempting both transpiling and running with ts-node, and have tried both Node 12 and 14. I'll give it a try without the multer typings

Can you share your repo with me if possible? I can take a look

shanurrahman-gcsns avatar Sep 24 '20 09:09 shanurrahman-gcsns

I can't share it as it's a private repo, but here's the relevant code and package.json:

import multer from 'multer';
//...
@UseBefore(multer(imgUploadOptions).fields([
	{ maxCount: 1, name: "img"},
	{ maxCount: 1, name: "icon"}
]))
async addGame(
	@Body() newGame : NewGameRequest,
	@Req() req : Request)
	: Promise<NewGameResponse>
{
export const imgUploadOptions : MulterOptions = {
	storage: memoryStorage(),
	fileFilter: (req : Request, file : File, acceptFile : FileFilterCallback) => {
		const allowedMimeTypes = [
			"image/jpeg",
			"image/png",
			"image/gif",
			"image/bmp",
			"image/tiff"
		];
		acceptFile(null, allowedMimeTypes.includes(file.mimetype));
	},
	limits: {
		fileSize: 1024 * 1024 * 8, // 8MB max file size
		files: 5 // max of five files at a time
	}
};

package.json:

"devDependencies": {
	"@types/body-parser": "^1.19.0",
	"@types/cookie-session": "^2.0.37",
	"@types/debug": "^4.1.5",
	"@types/express": "^4.17.1",
	"@types/express-handlebars": "^3.1.0",
	"@types/jimp": "^0.2.28",
	"@types/morgan": "^1.7.37",
	"@types/multer": "^1.4.4",
	"@types/ncp": "^2.0.4",
	"@types/node": "^9.6.5",
	"@types/passport": "^1.0.2",
	"@types/passport-discord": "^0.1.3",
	"ncp": "^2.0.0",
	"nodemon": "^1.19.3",
	"ts-node": "^8.4.1",
	"tslint": "^5.20.0",
	"typescript": "^3.3.3333"
},
"dependencies": {
	"axios": "^0.19.2",
	"body-parser": "^1.19.0",
	"chalk": "^3.0.0",
	"class-transformer": "0.2.3",
	"class-validator": "^0.12.2",
	"cookie-session": "^1.4.0",
	"cors": "^2.8.5",
	"debug": "^4.1.1",
	"discord.js": "^11.5.1",
	"express": "^4.17.1",
	"express-handlebars": "^3.1.0",
	"jimp": "^0.9.3",
	"morgan": "^1.9.1",
	"multer": "^1.4.2",
	"mysql2": "^1.7.0",
	"passport": "^0.4.1",
	"passport-discord": "^0.1.3",
	"reflect-metadata": "^0.1.13",
	"routing-controllers": "^0.9.0-alpha.6",
	"typeorm": "^0.2.0"
}

I've tried with and without my upload options, as well as the {dest} option that you tried, so I'm pretty sure it's nothing to do with that.

DiefBell avatar Sep 24 '20 09:09 DiefBell

function Multer (options) {
  if (options.storage) {
    this.storage = options.storage
  } else if (options.dest) {
    this.storage = diskStorage({ destination: options.dest })
  } else {
    this.storage = memoryStorage()
  }

  this.limits = options.limits
  this.preservePath = options.preservePath
  this.fileFilter = options.fileFilter || allowAll
}

This is from multer source code, here `https://github.com/expressjs/multer/blob/master/index.js`
They do have a default export for multer and all your options are also correct. The problem is not with how you are calling multer constructor. The problem is that node can't find multer at all. 
I can't infer anything else. May be install your dependencies agan and try. That's all I can say.

shanurrahman-gcsns avatar Sep 24 '20 09:09 shanurrahman-gcsns

So I've just imported it by doing

const multer = require("multer");

and that's now working fine...

DiefBell avatar Sep 24 '20 10:09 DiefBell

So I've just imported it by doing

const multer = require("multer");

and that's now working fine...

sorry @MerrickKing I was gone for some time, glad it worked out for you.

shanurrahman-gcsns avatar Oct 06 '20 11:10 shanurrahman-gcsns

Closing this as stale.

If the issue still persists, you may open a new Q&A in the discussions tab and someone from the community may be able to help.

attilaorosz avatar Dec 21 '22 16:12 attilaorosz

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Jan 21 '23 00:01 github-actions[bot]