New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for file uploads #96

Open
wants to merge 3 commits into
base: master
from

Conversation

Projects
None yet
9 participants
@ezra-quemuel
Copy link

ezra-quemuel commented May 9, 2017

  • Adds support for the @UploadedFile and @uploadedfiles decorators

  • Adds file upload support for Express and Koa using multer, and uses a custom middleware for Hapi

  • Exposes a File interface for an uploaded file

  • Fixes #93

@lukeautry

This comment has been minimized.

Copy link
Owner

lukeautry commented May 9, 2017

Thanks @ezra-quemuel! Looks pretty good; is there a way to upload the file to something other than the disk though?

@ezra-quemuel

This comment has been minimized.

Copy link

ezra-quemuel commented May 9, 2017

Not currently. The problem with adding that kind of extended functionality is that currently the Hapi middleware is custom. So any features like uploading a file to memory would have to be manually added to the custom Hapi middleware (which in that case, it should probably be its own library). I'd be fine with adding the support for Express and Koa, but if I do, I'd say that Hapi specifically would not be supported. Thoughts?

@ezra-quemuel

This comment has been minimized.

Copy link

ezra-quemuel commented May 9, 2017

As a note, Hapi currently doesn't have a standard library for file upload support AFAIK. I'm open to switching the implementation if there are better solutions.

@ezra-quemuel

This comment has been minimized.

Copy link

ezra-quemuel commented May 10, 2017

I've noticed a few issues related to swagger generation, so we should hold off on the merging of this PR. I'll have to add a FormData decorator to add support for extra form fields during file uploads (swagger doesn't allow body parameters with a multipart/form-data request, which makes sense).

@ezra-quemuel ezra-quemuel force-pushed the ezra-quemuel:feature/add-file-upload-support branch from e76a814 to 66a8851 May 12, 2017

Ezra Quemuel
- Add support for FormField decorator
- Add 'consumes: multipart/form-data' for files and form fields
- Disallow Body and BodyProps to be used with formData (Swagger Spec)

@ezra-quemuel ezra-quemuel force-pushed the ezra-quemuel:feature/add-file-upload-support branch from 66a8851 to 074bc09 May 12, 2017

@ezra-quemuel

This comment has been minimized.

Copy link

ezra-quemuel commented May 12, 2017

@lukeautry Updated.

  • Added support for the FormField decorator
  • Added validation to prevent Body and BodyProps to be used with any formData (swagger doesn't allow this)
  • Updated docs
  • Added "consumes: ['multipart/form-data']" when there is formData in the operation

@isman-usoh isman-usoh force-pushed the lukeautry:master branch from f848e15 to ac20c40 May 19, 2017

@ezra-quemuel

This comment has been minimized.

Copy link

ezra-quemuel commented May 22, 2017

@lukeautry fixed merge conflicts

@devanshah1

This comment has been minimized.

Copy link

devanshah1 commented Nov 22, 2017

@lukeautry Can we get this merged into master, and have a release pushed out. Thanks.

@egandro

This comment has been minimized.

Copy link
Contributor

egandro commented Feb 7, 2018

This one is also on my ToDo list. I'd like to have multer as middleware for express.

@egandro

This comment has been minimized.

Copy link
Contributor

egandro commented Feb 7, 2018

@ezra-quemuel is it ok with you that I take parts of your code and add a middleware like we have it in the authentication layer?

I'd love to have multer for this for express.js (https://github.com/expressjs/multer) we just need some custom function called that takes the request/response

@nartc

This comment has been minimized.

Copy link

nartc commented Feb 8, 2018

@egandro I’ve forked and added Multer support to the project. I never submitted a PR though because it is based off of this PR and I feel like it’s not really scalable. All it does was to add multer so that request.file returns the file selected, also added to the swaggerGenerator type: file and consumes: multipart/form-data

@nartc

This comment has been minimized.

Copy link

nartc commented Feb 8, 2018

I install the package on my personal project using my forked-repo so I do have the feature

@egandro

This comment has been minimized.

Copy link
Contributor

egandro commented Feb 8, 2018

@nartc Ok cool! I'll reintegrate it to this project.

I might create some driver structure as it is not 100% compatible with all supported web middlewares.

Also the multer feature needs by itself to be very flexible (file, ram or there is even multer s3)

I really love the swagger feature, because I've written code generators for android and angular ng clients on top of that!

@nartc

This comment has been minimized.

Copy link

nartc commented Feb 8, 2018

@egandro Me too. I'm currently using TSOA in a MEAN Stack application. I've tried the personally-added multer middleware last night and swagger-codegen generates method that takes in Blob for type: file in Swagger spec file. The backend receives the file and everything's fine. I'll hook it up to a S3 storage to see how it goes.

@AmazingTurtle

This comment has been minimized.

Copy link
Contributor

AmazingTurtle commented Feb 17, 2018

Until then I have added a short description on how to do this with multer "manually" (not that much effort though).

https://github.com/lukeautry/tsoa/pull/198/files

@nartc

This comment has been minimized.

Copy link

nartc commented Feb 20, 2018

@egandro just wanna update that I was able to upload file to Google Cloud Storage using multer in tsoa template.

Here's a code snippet of the controller.

@Post('{userId}')
    public async uploadUserImage(@Path() userId: string, @FormFile() image: MulterFileParameter): Promise<UserVm> {
        const user: User = await this._userRepository.getResourceById(userId);

        if (user instanceof MongoError) throw FileReferenceController.resolveErrorResponse(user as MongoError, user.message);
        if (!user) throw FileReferenceController.resolveErrorResponse(null, 'User not found');

        if (!image) throw FileReferenceController.resolveErrorResponse(null, 'Image cannot be null');

        const blob: File = this._gcStore.bucket.file(image.originalname);
        const blobStream: WriteStream = blob.createWriteStream({
            metadata: {
                contentType: image.mimetype
            }
        });

        blobStream.on('error', (error) => {
            throw FileReferenceController.resolveErrorResponse(error, 'Error uploading file');
        });

        return new Promise<UserVm>((resolve => {
            blobStream.end(image.buffer);
            blobStream.on('finish', async () => {
                const publicUrl: string = `https://storage.googleapis.com/${this._gcStore.bucket.name}/${blob.name}`;
                await this._gcStore.bucket.makePublic();

                const newFile: FileReference = new FileReferenceModel();
                newFile.publicUrl = publicUrl;
                newFile.fileName = image.filename ? image.filename : image.originalname;
                newFile.description = `${user.username}_profile`;
                newFile.sizeBytes = image.size;
                newFile.userId = user._id;
                newFile.source = image.originalname;

                user.image = await this._fileReferenceRepository.create(newFile);
                user.updatedOn = moment().toDate();
                resolve(await <UserVm>user.save());
            });
        }));
    }
@gabibianconi

This comment has been minimized.

Copy link

gabibianconi commented Mar 5, 2018

Hello, I would like to use TSOA in my project but I have to develop APIs with Files as parameters. When is this PR going to be merged into master?

@AmazingTurtle

This comment has been minimized.

Copy link
Contributor

AmazingTurtle commented Mar 5, 2018

@gabibianconi

This comment has been minimized.

Copy link

gabibianconi commented Mar 5, 2018

No, I didn't. I will take a look. Thanks!

@jamestharpe

This comment has been minimized.

Copy link
Contributor

jamestharpe commented May 25, 2018

Bump. The workaround... works, but having this feature be a part of TSOA would be even better!

@AmazingTurtle

This comment has been minimized.

Copy link
Contributor

AmazingTurtle commented May 25, 2018

This commit lasts for 1 year and I don't see someone would actually resolve merge conflicts... I'd take a look at this one myself when I have time.

@ryo-nbx

This comment has been minimized.

Copy link

ryo-nbx commented Sep 21, 2018

https://blog.nubix.de/index.php/2018/09/21/file-download-and-upload-with-tsoa-hack/

I put an example online demonstrating how to achieve upload and download files with the current version of TSOA. Downloading is a little bit dirty since file responses are not handled yet by TSOA.

I hope the example might help some user here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment