0

I'm having some troubles to upload files and data to my server using Angular 2 and PHP.

I've followed this File Upload In Angular 2? to upload the data and file from Angular 2 and all seems to be OK (I can see the data received by printing php://input). My Angular 2 code is something like this:

upload(data: data, file: File): Observable<any> {
  let header = new Headers();
  header.append('Content-Type', 'multipart/form-data');
  header.append('Accept', 'application/json');
  let options = new RequestOptions({ headers: header });

  let formData:FormData = new FormData();
  formData.append('file', file, file.name)
  formData.append('data', JSON.stringify({data}));

  return this.http
    .post('myurl', formData, options)
    .map(response => {
      return response;
    })
    .catch(error => Observable.throw(error.message || error));
}

The problem is that the superglobals $_POST and $_FILES aren't populated, so I can't access them (and the data and file uploaded so). I have the same problem when uploading only data and I solved it manually-populating the $_POST superglobal by doing

$_POST = file_get_contents("php://input");

but here I can't do this because of the $_FILES....

I see in this post PHP - empty $_POST and $_FILES - when uploading larger files that the problem could be that post_max_size or upload_max_filesize are small, but I set them to 100M (enought for my purposes) and still the same. Even I toured memory_limit higiher but nothing.

I think that my problem have to be in my server side, could be the headers I set or some configuration I missed. I discarded any CodeIgniter issue (I'm using last version of CodeIgniter) because I tryed to post to a simple php file and I have the same problem. The simplest server side I'm used is:

<?php
  header('Content-Type: application/json');
  header('Access-Control-Allow-Origin: *');
  header('Access-Control-Allow-Methods: GET, POST');
  header('Access-Control-Allow-Headers: Content-Type');

  exit(var_dump($_POST, $_FILES));
?>

But I get empty arrays...

Does anybody have any idea of what can I do?

1
  • I have tried a simple non-Angular2 multipart/form-data post request (I mean, a "standard" HTML post request as many years ago) and the $_POST and $_FILES variables were populated correctly... Commented Dec 10, 2017 at 21:47

1 Answer 1

0

I finally have found the solution to this problem.

In non-technical speaking (I'm not an expert), an htpp post multipart/form-data request use a boundary random string to identify the different parameters sent by the client in order to give the server a reference to parse the input. A valid request header looks like this:

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryYnNrniY34QSJ48LC

In my implementatation, when setting the request header as:

header.append('Content-Type', 'multipart/form-data');

no boundary is set so PHP can't parse the input to populete $_POST and $_FILES. I tried to define my own boundary by appending at the end of the header but it didn't work. But... The solution is even easier: there is no need to specify the Content-Type header, Angular 2 will make it by only passing the data as FormData and performing a post request, creating a valid boundary that PHP can use.

So, a valid code to do this is:

upload(data: data, file: File): Observable<any> {
  let formData:FormData = new FormData();
  formData.append('file', file, file.name)
  formData.append('data', JSON.stringify({data}));

  return this.http
    .post('myurl', formData)
    .map(response => {
      return response;
    })
    .catch(error => Observable.throw(error.message || error));
}

When performing this post request, Angular 2 will add a valid boundary in the multipart/form-data header.

That's all.

If someone can add more technical details about this, it would be great.

Hope this could help someone else.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.