简体   繁体   中英

Posting with content type multipart/form-data in Angular

I'm creating an API end point to upload files in .net core 2 as follow

 [HttpPost("{userId}/files")]
    public async Task<IActionResult> AddUserFile([FromRoute]string userId)
    {
        var file = Request.Form.Files.FirstOrDefault();

        var myFile = new MyFiles
        {
            FilePath = await UploadFile(file), // save the file and return url
            UserId = userId,
            FileName = Request.Form["fileName"],
            Description = Request.Form["description"]
        };

        // todo save file to database

        return Ok(myFile);
    }

I tested this end point using Postman and it works as expected.

when tried to call this end point from an Angular application as follow

onAddFile(form: NgForm) {

   const formData: FormData = new FormData();
   formData.append('', this.selectedFile);
   formData.append('fileName', form.value.fileName);
   formData.append('description', form.value.description);
   formData.append('userId', this.userId);

   const headers = new Headers();
   headers.append('accept-language', 'en');
   headers.append('Content-Type', 'multipart/form-data');
   headers.append('Authorization', `Bearer ${token}`);

   this.http.post(
     `https://localhost:44339/api/admin/users/${this.userId}/files`,
     formData,
     new RequestOptions({ headers: headers })
   ).subscribe(result => {
     console.log(result);
   });
 }

I get the following error

:44339/api/admin/users/c6d15e43-00b9-4eda-bac8-635f6017fec9/files:1 POST https://localhost:44339/api/admin/users/c6d15e43-00b9-4eda-bac8-635f6017fec9/files

edit:1 XMLHttpRequest cannot load https://localhost:44339/api/admin/users/c6d15e43-00b9-4eda-bac8-635f6017fec9/files . No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ' http://localhost:4200 ' is therefore not allowed access. The response had HTTP status code 500.

在此处输入图片说明

and this is the captured request header from the Angular app

:authority:localhost:44339
:method:POST
:path:/api/admin/users/c6d15e43-00b9-4eda-bac8-635f6017fec9/files
:scheme:https
accept:application/json
accept-encoding:gzip, deflate, br
accept-language:en-US,en;q=0.8,ar;q=0.6
authorization:Bearer eyJhbGciOiJIU.........
content-length:21531
content-type:multipart/form-data;
origin:http://localhost:4200
referer:http://localhost:4200/admin/users/c6d15e43-00b9-4eda-bac8-635f6017fec9/edit

and my request payload

------WebKitFormBoundaryqB4rbqWsrra0gwhi
Content-Disposition: form-data; name=""; filename="2017-08-22_21-56-02.png"
Content-Type: image/png


------WebKitFormBoundaryqB4rbqWsrra0gwhi
Content-Disposition: form-data; name="fileName"

er
------WebKitFormBoundaryqB4rbqWsrra0gwhi
Content-Disposition: form-data; name="description"

df
------WebKitFormBoundaryqB4rbqWsrra0gwhi
Content-Disposition: form-data; name="userId"

c6d15e43-00b9-4eda-bac8-635f6017fec9
------WebKitFormBoundaryqB4rbqWsrra0gwhi--

while trying to figure out the issue I noticed that this happens only if the request content-type is multipart/form-data , which I have to use in this case to be able to upload the file.

what am I missing here, am I doing some thing wrong in angular or I missed a configuration in the server side API?


Edit:

cors configuration in startup

  app.UseCors(builder =>
                builder
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowAnyOrigin()
                    .AllowCredentials()
            );

I was able to overcome this issue finally, the fix is to delete the content type from the header

headers.delete('Content-Type');

don't leave it empty this will cause an error

Incorrect Content-Type: , multipart/form-data; boundary

You have to enable the CORS on backend as suggested by A.Tim. Following is how it is done in Java for a Spring based app.

public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry corsRegistry) {
            corsRegistry.addMapping("/**").allowedMethods("*").allowedHeaders("*").allowedOrigins("*");
        }
    };
}

I believe you have a typo in Angular's http url:

https://localhost:44339/api/admin/users/ ${this.userId}/files

It should be (note the port)

https://localhost:4200/api/admin/users/ ${this.userId}/files

Or better yet, use a relative url so the host is automatically calculated.

If you're actually runing these 2 apps in localhost make sure the one in port 44339 has CORS configured.

Chrome is throwing this error because you are sending a request to a host in a different port. Note that only for testing purposes you can temporally disable this security measure locally in Chrome, if you have Windows press Win+R and then execute:

chrome --disable-web-security --user-data-dir

(you must first close all Chrome instances, including Postman)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM