nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
67.47k stars 7.6k forks source link

`UploadFile()` should accept `Readable` instead of `Buffer` #13158

Open samchon opened 8 months ago

samchon commented 8 months ago

Is there an existing issue that is already proposing this?

Is your feature request related to a problem? Please describe it

When using @UploadFile() decorator following the NestJS guide documents, it becomes Buffer type.

As you know, the Buffer type means that backend server gathers entire data of the uploaded file. If client uploads 1GB file through the API, the NestJS backend server requires at least 1GB memory about the request. If there're 100 clients uploading the 1GB file at the same time, NestJS backend server needs 100GB memory at that time.

Describe the solution you'd like

I know that the default option of multer is using the Buffer type instance, but it seems not proper to the full framework like NestJS. If configure storage engine of the multer, the uploadaed file would be Readable stream type, and I think NestJS should do it.

Teachability, documentation, adoption, migration strategy

I have followed the https://docs.nestjs.com/techniques/file-upload document.

And very surprised by too much memory consumption.

What is the motivation / use case for changing the behavior?

I think NestJS should do like below:

  1. Make streaming to be default
  2. When some users want Buffer feature, they must configure by themselves
  3. If hard to migrate, then have to warn those facts in the guide documents
jmcdo29 commented 8 months ago

The thing is, it can accept Readable as you mentioned, with the right configuration. While it may be a better solution, in terms of memory management, it's also a more advanced solution in terms of Node API knowledge as not everyone is well versed with streams, and it's a breaking change at the moment. We'd have to make sure to update the docs to show how the stream could be worked with, and probably be ready to answer many, many more questions on how to use the newer approach, which would inevitably be sent to Discord or StackOverflow and answered there.

While I do think that better memory management is a good thing, there is a balance to be kept between efficient and ergonomic API for developers.

jmcdo29 commented 8 months ago

Perhaps we can make a mention in the docs and the default of buffer and how to use streams if that is the desired approach and why you might want to do that

samchon commented 8 months ago

If hope to avoid breaking change, I think NestJS guide document must warn the memory problem, and give an example code converting to the streaming strategy.

kamilmysliwiec commented 8 months ago

Adding a mention in the docs sounds valuable

samchon commented 8 months ago

I'd tried to make concise @UploadFile() similar decorator supports both express and fastify, and understood why @kamilmysliwiec and @jmcdo29 had configured of @UploadFile() to just utilize the full Buffer data as default. To perform streaming, have to configure storage engine of multer, but it was not easy to determine which option to adjust as default.

On the other hand, fastify's multipart/form-data was much easier to handle. This is because streaming could be used right away without any additional settings. Therefore, I had developed @TypedFormData.Body() to utillize the full data Buffer to compatible with both express and fastify, and planning to apply memory storage to the multer side by referring to fastify's options.

Anyway, after I completed this @TypedFormData.Body() and studied it thoroughly through various experiments, I will contribute to Nest Document. The next PR may be the next month.

Shandur commented 3 months ago

@samchon Have you had any chance to contribute to NestJS documentation? :)

samchon commented 3 months ago

Have forgotten this issue for a long time due to busy.

@Shandur Thanks for reminding. It's okay you to contribute eariler.