question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Content-type problem when sending json AND file in same FormData

See original GitHub issue

Bug Report

Hello.

Affected Package

The issue is caused by package @angular/common/http (HttpClient)

Is this a regression?

I have no idea. I never did anything similare before I post this issue there.

Description

I am sorry, I won’t be able to provide a Minimal Reproduction since it require a back-end as well (I use Spring Boot here) so the description will contain all the detail you’ll need.

– Short:

What I want: I’m trying to send a FormData that contains a JSON and a File (in the same FormData).

What I expect: The function on the back-end that is responsible of the API (a DTO, a Multipartfile) should be able to get the JSON + the file.

What I have: The DTO contains only null values, I correctly get the file.

Additional information: Why I’m posting here is because, using Postman, all works as expected.

– Long:

Here is an example of what I’m doing.

Front-End service function:

createToto(totoDTO: TotoDTO, file: File): Observable<void> {
    const formData = new FormData();

    formData.append('toto', JSON.stringify({ totoDTO }));
    formData.append('file', file, file.name);

    return this.http.post<void>(`${TotoService.URL}`, formData);
}

Back-End controller function:

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public void createToto(@RequestPart("toto") TotoDTO totoDTO, @RequestPart("file") MultipartFile multipartFile, Principal loggedUser) throws IOException {
    System.out.println(totoDTO);
    System.out.println(multipartFile.getOriginalFilename());
    //totoService.createToto(totoDTO, multipartFile, loggedUser.getName());
}

So when I send a request from the Front-End to the Back-End, the Back-End tell me that Content type 'application/octet-stream' not supported:

2021-06-24 16:04:17.812  WARN 18820 --- [nio-8080-exec-5] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]

The request header looks like this (it’s a content-type multipart):

------WebKitFormBoundary4WervCkSHzbAcd2L
Content-Disposition: form-data; name="toto"

{"toto":{"id":6,"unChamp":"coucou"}}
------WebKitFormBoundary4WervCkSHzbAcd2L
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain


------WebKitFormBoundary4WervCkSHzbAcd2L--

I did some research and then found out that for the DTO it should be stored in a Blob like this:

...
formData.append(
    'toto',
    new Blob([JSON.stringify({ totoDTO })], {
        type: 'application/json'
    })
);
...

The request header looks like this, here the DTO have Content-Type: application/json which should be fine:

------WebKitFormBoundaryocSMA44WAWzYVkwC
Content-Disposition: form-data; name="toto"; filename="blob"
Content-Type: application/json

{"toto":{"id":6,"unChamp":"coucou"}}
------WebKitFormBoundaryocSMA44WAWzYVkwC
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain


------WebKitFormBoundaryocSMA44WAWzYVkwC--

Fine, the Back-End doesn’t cry anymore but the json received on the Back-End seems to be empty or isn’t in the good form:

TotoDTO(id=null, unChamp=null)
test.txt

So, why am I posting an issue here?

Because if I’m using Postman, all works as intended: Image collée à 2021-6-24 16-43

I get the proper DTO (nothing null) and the file.

I suspect something being wrong on the Angular side, either it’s my fault on not properly setting something or it’s a “bug”.

Maybe I’m not thinking properly and shouldn’t send a file with a json (DTO) ? I don’t want to use 2 differents request for that. Maybe It’s better to send a base64 file?

Your Environment

Angular Version:



     _                      _                 ____ _     ___ 
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | | 
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | | 
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/



Angular CLI: 11.2.11
Node: 14.16.1
OS: win32 x64

Angular: 11.2.12
... animations, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1102.11
@angular-devkit/build-angular   0.1102.11
@angular-devkit/core            11.2.11
@angular-devkit/schematics      11.2.11
@angular/cdk                    11.2.11
@angular/cli                    11.2.11
@angular/material               11.2.11
@schematics/angular             11.2.11
@schematics/update              0.1102.11
rxjs                            6.6.7
typescript                      4.1.5

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
JoostKcommented, Jun 24, 2021

You appear to be hitting specific Spring behavior where a request part with a filename in its Content-Disposition header is interpreted as a file:

https://github.com/spring-projects/spring-framework/blob/ddbb7c1b5b003018ee4ebd483ca4a22dd60a53c7/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java#L98-L108

When making the request from Postman it’s likely not including the filename="blob" data, which avoids Spring from interpreting it as a file.

I’m afraid there isn’t anything we can do from the Angular side of things, as handling of FormData is entirely up to the browser.

0reactions
angular-automatic-lock-bot[bot]commented, Jul 26, 2021

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

Read more comments on GitHub >

github_iconTop Results From Across the Web

sending file and json in POST multipart/form-data request with ...
On the server Content-Type for document is text/plain;charset=us-ascii . Update: I managed to make a correct request via Postman, by sending ...
Read more >
Is it possible to upload a file with other data on the same ...
I try to upload a file with other fields like name, birth date , .... the problem is : using Axios I have...
Read more >
Sending a JSON file within a Multipart-form data HTTP POST
I am trying to upload a JSON file along with a PDF file to a REST API using Flow's HTTP POST command using...
Read more >
How to send application/json data along with file in postman ...
The question is regarding sending files with a Content-Type "application/json" including the file (which is not JSON). Many people seem to ...
Read more >
Using the Fetch API - MDN Web Docs
Here we are fetching a JSON file across the network and printing it to the console. The simplest use of fetch() takes one...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found