quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.87k stars 2.71k forks source link

Support to list all multipart uploads but without storing them locally #43127

Open Eng-Fouad opened 2 months ago

Eng-Fouad commented 2 months ago

Description

Currently, one can list all file uploads in a multipart/form-data request, as follows:

@RestForm(FileUpload.ALL) List<FileUpload> fileUploads;

However, this will store the files in a temp directory.

Alternatively, one can define multiple parameters:

@RestForm("file1") byte[] file1;
@RestForm("file2") byte[] file2;
@RestForm("file3") byte[] file3;

but this is not a dynamic listing.

So this is an enhancement request to support listing them but without storing them locally on the filesystem (i.e. fileItem.isInMemory() is true):

@RestForm(FileUpload.ALL) Map<String, byte[]> fileUploads; // where keys are part names
// or
@RestForm(FileUpload.ALL) List<FileItem> fileUploads; // where fileItem.isInMemory() is true

Implementation ideas

No response

quarkus-bot[bot] commented 2 months ago

/cc @FroMage (rest), @stuartwdouglas (rest)

geoand commented 2 months ago

An alternative is to use MultipartFormDataInput. That assumes no structure whatsoever so you can iterate through all the items of the request.

Eng-Fouad commented 2 months ago

An alternative is to use MultipartFormDataInput. That assumes no structure whatsoever so you can iterate through all the items of the request.

When using MultipartFormDataInput, fileItem.isInMemory() is always false for me.

geoand commented 2 months ago

Do you have a sample I can look at?

Eng-Fouad commented 2 months ago

Do you have a sample I can look at?

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/upload-files")
public void uploadFiles(MultipartFormDataInput input) throws IOException {
    int partCount = 0;
    for (var entry : input.getValues().entrySet()) {
        Log.infof("Part #%d:", ++partCount);
        Log.info("\t- Name: " + entry.getKey());
        for (var formValue : entry.getValue()) {
            boolean isFileItem = formValue.isFileItem();
            Log.info("\t- IsFile?: " + isFileItem);
            if (isFileItem) {
                var fileItem = formValue.getFileItem();
                boolean isInMemory = fileItem.isInMemory();
                Log.info("\t- isInMemory?: " + isInMemory);
                if (isInMemory) {
                    byte[] bytes = ((ByteArrayInputStream) fileItem.getInputStream()).readAllBytes();
                    Log.info("\t- byte[] length: " + bytes.length);
                } else {
                    Log.info("\t- File path: " + fileItem.getFile());
                }
            } else {
                Log.info("\t- String value: " + formValue.getValue());
            }
        }
    }
}
geoand commented 2 months ago

Thanks.

And the request you are making is?

Eng-Fouad commented 2 months ago

Thanks.

And the request you are making is?

I am using Postman to submit the request:

11

The console output:

2024-09-09 13:13:34,943 INFO  [com.exa.ExampleResource] (executor-thread-1) Part #1:
2024-09-09 13:13:34,944 INFO  [com.exa.ExampleResource] (executor-thread-1)     - Name: abc
2024-09-09 13:13:34,944 INFO  [com.exa.ExampleResource] (executor-thread-1)     - IsFile?: false
2024-09-09 13:13:34,944 INFO  [com.exa.ExampleResource] (executor-thread-1)     - String value: 123
2024-09-09 13:13:34,944 INFO  [com.exa.ExampleResource] (executor-thread-1) Part #2:
2024-09-09 13:13:34,945 INFO  [com.exa.ExampleResource] (executor-thread-1)     - Name: file1
2024-09-09 13:13:34,945 INFO  [com.exa.ExampleResource] (executor-thread-1)     - IsFile?: true
2024-09-09 13:13:34,945 INFO  [com.exa.ExampleResource] (executor-thread-1)     - isInMemory?: false
2024-09-09 13:13:34,945 INFO  [com.exa.ExampleResource] (executor-thread-1)     - File path: C:\Users\fouad\AppData\Local\Temp\uploads\resteasy-reactive9116967901438797957upload
geoand commented 2 months ago

Thanks. I'll have a look soon

geoand commented 2 months ago

Anything that contains a filename attribute in a multipart part, is treated as a file.

Eng-Fouad commented 2 months ago

Anything that contains a filename attribute in a multipart part, is treated as a file.

Is there a way to prevent saving file locally even if it has a name?

geoand commented 2 months ago

There is not, but I guess we could look into making it happen...