Skip to content
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

[Feature]: Rest API Plugin: provide option to upload binary data (multimedia files) #32378

Closed
1 task done
sumitsum opened this issue Apr 3, 2024 · 4 comments · Fixed by #32921
Closed
1 task done
Assignees
Labels
Backend This marks the issue or pull request to reference server code BE Coders Pod Issues related to users writing code to fetch and update data Enhancement New feature or request Frontend This label marks the issue or pull request to reference client code High effort More than a sprint High This issue blocks a user from building or impacts a lot of users Integrations Pod Issues related to a specific integration Needs Design needs design or changes to design Production QA Pod Issues under the QA Pod QA Needs QA attention REST API plugin REST API plugin related issues

Comments

@sumitsum
Copy link
Contributor

sumitsum commented Apr 3, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Summary

Currently REST API plugin does not seem to have any option that allows users to directly transmit binary data / file content .
e.g. Postman provides a binary tab:
https://theappsmith.slack.com/files/U035SFJHW3A/F06S5N2BUTX/image.png

Why should this be worked on?

This should take away a lot of confusion related with file uploads using REST API query.

Front logo Front conversations

@sumitsum sumitsum added Enhancement New feature or request Frontend This label marks the issue or pull request to reference client code Backend This marks the issue or pull request to reference server code Needs Design needs design or changes to design REST API plugin REST API plugin related issues labels Apr 3, 2024
@github-actions github-actions bot added Integrations Pod Issues related to a specific integration labels Apr 3, 2024
@sumitsum
Copy link
Contributor Author

sumitsum commented Apr 11, 2024

APMU, binary data upload is completely non functional via REST API app. Reasons:

  1. On the server side dynamic binding data is converted from binary to either a UTF-8 or ISO_8859_1 string, both of which could lead to binary data corruption. To maintain the sanctity of binary data, it should be either stored as byte array or converted to base64.
  2. Needs to be checked : does the client try to convert any binary data to String format before sending it to the server - if so then binary data must be converted to base64 string before sending it server. Converting it to any other char set format String e.g. utf-8 could cause data corruption.

Relevant code sections:

protected Mono<Param> parseExecuteParameter(Part part, AtomicLong totalReadableByteCount) {
        final Param param = new Param();
        param.setPseudoBindingName(part.name());
        return DataBufferUtils.join(part.content()).map(dataBuffer -> {
            byte[] bytes = new byte[dataBuffer.readableByteCount()];
            totalReadableByteCount.addAndGet(dataBuffer.readableByteCount());
            dataBuffer.read(bytes);
            DataBufferUtils.release(dataBuffer);
            param.setValue(new String(bytes, StandardCharsets.UTF_8));
            return param;
        });
    }
protected Mono<Void> parseExecuteBlobs(
            Flux<Part> partsFlux, ExecuteActionDTO dto, AtomicLong totalReadableByteCount) {
        Map<String, String> blobMap = new HashMap<>();
        dto.setBlobValuesMap(blobMap);

        return partsFlux
                .flatMap(part -> {
                    return DataBufferUtils.join(part.content()).map(dataBuffer -> {
                        byte[] bytes = new byte[dataBuffer.readableByteCount()];
                        totalReadableByteCount.addAndGet(dataBuffer.readableByteCount());
                        dataBuffer.read(bytes);
                        DataBufferUtils.release(dataBuffer);
                        blobMap.put(part.name(), new String(bytes, StandardCharsets.ISO_8859_1));
                        return Mono.empty();
                    });
                })
                .then();
    }

A possible feature implementation to enable binary file upload:

  1. Provide a new tab in the body section called binary. On selecting this tab the content type should auto set to applicaton/octet-stream
  2. In the new binary body tab, any file data must be provided as base64 string.
  3. On the server add special handling for application/octet-stream content type. It should assume that the body data is base64 string and decode it to byte array.

@NilanshBansal NilanshBansal added High This issue blocks a user from building or impacts a lot of users Production High effort More than a sprint labels Apr 11, 2024
@github-actions github-actions bot added the BE Coders Pod Issues related to users writing code to fetch and update data label Apr 11, 2024
@sumitsum
Copy link
Contributor Author

Reasons why this could be treated as high priority issue:

  • This is a very basic and recurring use case that is expected via REST API .
  • Postman has a separate section to upload binary files. Many Postman users expect to see something similar here as well.
  • Until this issue is addressed we can expect to see this issue reported by users to A force from time to time - taking up valuable bandwidth from the Integrations team.
  • At the moment Appsmith documentation mentions that binary files can be uploaded via REST API. This is not true at the moment. Hence, the documentation would have to be updated. However, explicitly mentioning that binary files upload is not support would look bad because this a basic use case.
    cc: @rohan-arthur @NilanshBansal

@NilanshBansal
Copy link
Contributor

Mentioned this in the Sprint Planning Doc for us to plan it in the Next Sprint.
https://www.notion.so/appsmith/9-Apr-2024-43c9fc673b8d4b91b65826470ff1a761?pvs=4#f7234aeb1d5041eb978d795b47440751

@PrasannaPtools
Copy link

This a problem I was running into. I tried uploading a photoshop file through the file uploader to a dropbox endpoint and the resulting file gives me an error when I try to open it.

Context

  • Self hosted on Digital Ocean Droplet
  • Version Appsmith v1.13

Summary

I upload a small photoshop file (71 KB) onto the file uploader and click upload.

The triggered query, upon file upload, is a POST request to this endpoint ("https://content.dropboxapi.com/2/files/upload").

I set the data format to binary in the file uploader widget and in the query's body I refer to the uploading file as {{DropboxFilePicker.files[0].data}}.

image

image

After uploading I receive a larger file in dropbox (147 KB). When I try to open the uploaded file I get the following error.

image

@sumitsum sumitsum changed the title [Feature]: Rest API Plugin: provide option to upload binary data [Feature]: Rest API Plugin: provide option to upload binary data (multimedia files) Apr 19, 2024
@sneha122 sneha122 self-assigned this Apr 24, 2024
sneha122 added a commit that referenced this issue Apr 29, 2024
## Description
If we use REST API action and file picker widget to upload any
multimedia files (image, audio, video, pdf, xlsx), The file upload would
be successful but file would get corrupted upon uploading. This was
happening because file picker widget encodes this file to base64 format,
and we were uploading this same base64 string using REST API url.
Instead we should have decoded this base64 and then uploaded the file to
retain the original contents of the file.

This PR fixes that issue by adding a new tab in body of the REST API
action called `binary`, once we select this tab, we get autogenerated
header for `Content-Type: application/octet-stream`, in this binary
input field we can then provide base64 encoded file contents, the server
then decodes the contents before triggering the respective REST API and
uploading the file.

### Steps to test the issue
1. Add a file picker widget on canvas
2. Select data format as `Base64`
3. Upload any of pdf, image, audio, video, xlsx in file picker
4. Create a REST API action using [Dropbox upload
API](https://www.dropbox.com/developers/documentation/http/documentation#files-upload)
5. Configure the API headers as mentioned in the documentation, also
configure file name in the header correctly
6. Go to body tab, select binary and file contents in input box using
binding like {{Filepicker1.files[0].data}}
7. Execute this API
8. Now go to your dropbox account and check the uploaded file, you
should be able to successfully preview it


Fixes #32378  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

/ok-to-test tags="@tag.Datasource"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/8844375718>
> Commit: 3316290
> Cypress dashboard url: <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=8844375718&attempt=1"
target="_blank">Click here!</a>

<!-- end of auto-generated comment: Cypress test results  -->








## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added support for binary file uploads in API requests, including
handling of base64-encoded files.
- Expanded content type options to include a new "BINARY" type for API
requests.

- **Tests**
- Implemented new tests to verify the functionality of binary file
uploads with dynamic data binding.

- **Bug Fixes**
- Ensured correct handling and auto-generation of headers for binary
file types and form urlencoded data formats.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: “sneha122” <“sneha@appsmith.com”>
@appsmith-bot appsmith-bot added the QA Needs QA attention label Apr 29, 2024
@github-actions github-actions bot added the QA Pod Issues under the QA Pod label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backend This marks the issue or pull request to reference server code BE Coders Pod Issues related to users writing code to fetch and update data Enhancement New feature or request Frontend This label marks the issue or pull request to reference client code High effort More than a sprint High This issue blocks a user from building or impacts a lot of users Integrations Pod Issues related to a specific integration Needs Design needs design or changes to design Production QA Pod Issues under the QA Pod QA Needs QA attention REST API plugin REST API plugin related issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants