tsedio / tsed

:triangular_ruler: Ts.ED is a Node.js and TypeScript framework on top of Express to write your application with TypeScript (or ES6). It provides a lot of decorators and guideline to make your code more readable and less error-prone. ⭐️ Star to support our work!
https://tsed.io/
MIT License
2.86k stars 284 forks source link

[BUG] MulterFile #778

Closed IARKI closed 4 years ago

IARKI commented 4 years ago

Information

A few sentences describing the overall goals of the issue.

Example

@Controller("/files")
@UseAuth(AuthMiddleware, {roles: [EUserRoles.ADMIN]})
export class AdminFilesController {

    @Put("/upload")
    @MulterOptions({dest: '/testFolder'})
    async uploadFile(@MultipartFile("fileName") file: Express.Multer.File) {
        return true;
    }
}

On starting server I'm getting next error

{ INJECTION_ERROR: Injection failed on PlatformModule
Origin: Route.put() requires a callback function but got a [object Object]
    at Function.throwInjectorError (project\node_modules\@tsed\di\src\errors\InjectionError.ts:43:11)
    at Map.resolve (project\node_modules\@tsed\di\src\services\InjectorService.ts:529:22)
    at Map.invoke (project\node_modules\@tsed\di\src\services\InjectorService.ts:195:38)
    at Object.<anonymous> (project\node_modules\@tsed\common\src\server\utils\loadInjector.ts:16:12)
    at Generator.next (<anonymous>)
    at project\node_modules\tslib\tslib.js:110:75
    at new Promise (<anonymous>)
    at Object.__awaiter (project\node_modules\tslib\tslib.js:106:16)
    at Object.loadInjector (project\node_modules\@tsed\common\lib\server\utils\loadInjector.js:7:20)
    at Server.<anonymous> (project\node_modules\@tsed\common\src\server\components\ServerLoader.ts:409:11)
    at Generator.next (<anonymous>)
    at fulfilled (project\node_modules\tslib\tslib.js:107:62)
    at process._tickCallback (internal/process/next_tick.js:68:7)
    at Function.Module.runMain (internal/modules/cjs/loader.js:834:11)
    at main (project\node_modules\ts-node\src\bin.ts:226:14)
    at Object.<anonymous> (project\node_modules\ts-node\src\bin.ts:485:3)
  name: 'INJECTION_ERROR',
  tokens: [ [Function: PlatformModule] ],
  origin:
   Error: Route.put() requires a callback function but got a [object Object]
       at Route.(anonymous function) [as put] (project\node_modules\express\lib\router\route.js:202:15)
       at Function.proto.(anonymous function) [as put] (project\node_modules\express\lib\router\index.js:510:19)
       at PlatformRouter.addRoute (project\node_modules\@tsed\common\src\platform\services\PlatformDriver.ts:17:21)
       at pathsMethods.forEach (project\node_modules\@tsed\common\src\platform\builder\ControllerBuilder.ts:94:14)
       at Array.forEach (<anonymous>)
       at ControllerBuilder.buildEndpoint (project\node_modules\@tsed\common\src\platform\builder\ControllerBuilder.ts:91:18)
       at endpoints.forEach.endpoint (project\node_modules\@tsed\common\src\platform\builder\ControllerBuilder.ts:65:12)
       at Array.forEach (<anonymous>)
       at ControllerBuilder.buildEndpoints (project\node_modules\@tsed\common\src\platform\builder\ControllerBuilder.ts:64:15)
       at ControllerBuilder.build (project\node_modules\@tsed\common\src\platform\builder\ControllerBuilder.ts:28:8)
       at injector.getProviders.map.provider (project\node_modules\@tsed\common\src\platform\services\Platform.ts:52:72)
       at Array.map (<anonymous>)
       at Platform.createRoutersFromControllers (project\node_modules\@tsed\common\src\platform\services\Platform.ts:50:8)
       at new PlatformModule (project\node_modules\@tsed\common\src\platform\PlatformModule.ts:11:14)
       at construct (project\node_modules\@tsed\di\src\services\InjectorService.ts:593:46)
       at Map.resolve (project\node_modules\@tsed\di\src\services\InjectorService.ts:527:18) }

If I remove @MultipartFile("fileName") file: Express.Multer.File everything works fine

Romakita commented 4 years ago

Hello @IARKI,

Have you the same version between @tsed/multer and @tsed/common ?

IARKI commented 4 years ago

do you mean @tsed/multipartfiles"? "@tsed/multipartfiles": "^5.44.6", "@tsed/common": "^5.44.6"

IARKI commented 4 years ago

Same error happens if I use @UseBefore(AnyMiddleware, {data: "anydata"}) If that is helpful

Romakita commented 4 years ago

So the problem isn't about multer but about UseAuth and UseBefore. I'll check that.

Romakita commented 4 years ago

I cannot reproduce. The example here https://github.com/TypedProject/tsed/tree/production/examples/multer works as expected (I added a UseBefore decorator). Can you checkout this example and try it.

If your problem persist, can you give me a reproductible repository example please :)

See you Romain

IARKI commented 4 years ago

updating to 5.44.9 fixed the issue It looks like https://github.com/TypedProject/tsed/commit/3f36f91381b14f6be30e57601453e983518ef461 fixed the issue

Thanks

gangasiddhi commented 4 years ago

still this issue occur after upgrading to 5.44.9

Romakita commented 4 years ago

@gangasiddhi can you checkout this example: https://github.com/TypedProject/tsed/tree/production/examples/multer and try it. If you haven’t problems, can you give me a reproductible repository example please :)

gangasiddhi commented 4 years ago

And am not able to see the upload option in the swagger.

gangasiddhi commented 4 years ago

controllers/upload.ts

import { Controller, Status, Post } from '@tsed/common';
import { MultipartFile } from '@tsed/multipartfiles';
//import {Responses} from "@tsed/swagger";
//import { csvFileService } from './../services/uploadFIle';

@Controller('/')
export class saltgroupController {
    constructor(private csvFileService: csvFileService) {}

    @Post('/files')
    @Status(201)
    @Responses("201", {description: "Uploaded"})
     async getData(@MultipartFile("file") file: Express.Multer.File): Promise<any> {
      return true;
    }
}

server setting at server.ts

@ServerSettings({
    //server settings need to be implemented
    rootDir,
    httpPort: config.get<number>('server.port'),
    httpsPort: false,
    mount: {
        '/': `${rootDir}/controllers/**/*.ts`
    },
    uploadDir: `${rootDir}/uploaded-files`,
    swagger: [
        {
            path: '/docs'
        }
    ],
    multer: {
        dest: `${rootDir}/uploaded-files`
    },
    acceptMimes: ['application/json','multipart/form-data'],
    componentsScan: [
        '${rootDir}/services/**/*.ts',
        '${rootDir}/middlewares/**/*.ts',
        '${rootDir}/interfaces/**/*.ts'
        // "${rootDir}/tests/**/*.ts"
    ]
})
Romakita commented 4 years ago

With the official example, the upload file appear:

Capture d’écran 2020-03-18 à 16 58 18

And based on your example, I have the same result.

I can't reproduce your problem. So if you give an access to your repository (or a repository with only the necessary code to reproduce the problem), I can take a look :)

See you, Romain

gangasiddhi commented 4 years ago

Still the same issue, i used the sample code as it is.

gangasiddhi commented 4 years ago
{
  "name": "ABC",
  "version": "2.0.0",
  "description": "ABC",
  "keywords": [],
  "license": "ISC",
  "author": "",
  "main": "index.js",
  "scripts": {
    "start": "nps",
    "test": "nps test"
  },
  "dependencies": {
    "@tsed/common": "5.44.9",
    "@tsed/core": "5.44.9",
    "@tsed/di": "5.44.9",
    "@tsed/logger": "^5.4.1",
    "@tsed/multipartfiles": "^5.44.9",
    "@tsed/swagger": "5.44.9",
    "@types/papaparse": "^5.0.3",
    "@types/request-promise-native": "^1.0.17",
    "@types/swagger-schema-official": "^2.0.20",
    "body-parser": "^1.19.0",
    "compression": "^1.7.4",
    "config": "^3.2.5",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "helmet": "^3.21.2",
    "jest-junit": "^10.0.0",
    "knex": "^0.20.9",
    "morgan": "^1.9.1",
    "multer": "^1.4.2",
    "objection": "^2.1.2",
    "papaparse": "^5.1.1",
    "pg": "^7.18.1",
    "request": "^2.88.2",
    "request-promise-native": "^1.0.8",
    "source-map-support": "^0.5.16"
  },
  "devDependencies": {
    "@tsed/testing": "^5.44.9",
    "@types/compression": "^1.7.0",
    "@types/config": "0.0.36",
    "@types/cors": "^2.8.6",
    "@types/express": "^4.17.2",
    "@types/helmet": "0.0.45",
    "@types/jest": "^25.1.3",
    "@types/morgan": "^1.7.37",
    "@types/node": "^13.9.1",
    "@types/request-promise-native": "^1.0.17",
    "@typescript-eslint/eslint-plugin": "^2.23.0",
    "@typescript-eslint/parser": "^2.23.0",
    "eslint": "^6.8.0",
    "eslint-config-prettier": "^6.10.0",
    "eslint-plugin-import": "^2.20.1",
    "eslint-plugin-prettier": "^3.1.2",
    "eslint-plugin-simple-import-sort": "^5.0.1",
    "eslint-plugin-sonarjs": "^0.5.0",
    "jest": "^25.1.0",
    "nps": "^5.9.12",
    "nps-utils": "^1.7.0",
    "rimraf": "^3.0.2",
    "ts-jest": "^25.2.1",
    "tsc-watch": "^4.1.0",
    "typescript": "^3.8.2",
    "wait-on": "^4.0.0"
  }
}
Romakita commented 4 years ago

Ok now your problem is clear :). Multer package works as expected. Do you use webpack to run your server? What is executed by nps under the hood?

There is a know issue about stack based on webpack/jest (no espacially for Ts.ED, typeorm also has it). When you use this stack, you have to import all class (controller, etc,...) explicitly with ES6. Dynamic import won’t work (componantScan with globpattern).

Can you change your Server configuration please :)

I close this issue, the problem isn’t probably about @tsed/multipartfiles but from your stack. See you

gangasiddhi commented 4 years ago

npm install --save @types/multer, fixed the issue.

thanks @Romakita for the quick reply.

Romakita commented 4 years ago

@gangasiddhi Ha ok :)

I'm interested by your stack based on jest. I working on the @tsed/cli and one of the feature, is to generate project based on Jest framework. It's possible to share a minimal repository on git based on your stack please :)?

See you Romain