3

I'm using restangular 1.51 with angular 1.6. My html looks like this

<input type="file" name="file" />

and the angular code (based on the discussion here):

let directive = {
  ..
  link: (scope, element, attrs) => {
        let inputElement = angular.element(element[0].querySelector('input'));
        inputElement.bind('change', function () {
        var formData = new FormData();
        formData.append('file', inputElement[0].files[0]);

        API.all('stores/csv').withHttpConfig({transformRequest: angular.identity})             .customPOST(formData,'' , undefined,
          { 'Content-Type': undefined }).then((response) => {console.log(response);
          });
    });

laravel code:

public function upload(Request $request)
{

    $this->validate($request, [
        'file' => 'required',
        'type'  => 'in:csv,xls,xlsx',
        ]);

    $file = $request->file('file');
    var_dump($file);
    return response()->success(['file' => $file]);
}

thing is the $file here is appearing as an empty array in the laravel dump. The documentation is pretty bad on this. Ideas?

update

It works just fine using postman. this is the curl generated by postman:

postman curl:

curl -X POST \
  http://127.0.0.1:8000/api/stores/csv \
  -H 'Accept: application/x.toters.v1+json' \
  -H 'Authorization: Bearer ***' \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Postman-Token: 4f9d2f3b-551b-aa47-4f65-98c7582f2919' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F file=@/Users/Shared/Download/bac-383-store-update.csv

postman server logs

[2018-03-03 06:35:18] local.INFO: ----------------------------- [] []
[2018-03-03 06:35:18] local.INFO: POST api/stores/csv [] []
[2018-03-03 06:35:18] local.INFO: array (   'file' =>    Illuminate\Http\UploadedFile::__set_state(array(      'test' => false,      'originalName' => 'bac-383-store-update.csv',      'mimeType' => 'text/csv',      'size' => 62,      'error' => 0,   )), ) [] []
[2018-03-03 06:35:18] local.INFO: Status code: 200 [] []
[2018-03-03 06:35:18] local.INFO: User id: 104 [] []

this is the curl generated by restangular

restangular (two requests - using chrome) curl:

curl 'http://127.0.0.1:8000/api/stores/csv' 
-X OPTIONS 
-H 'Access-Control-Request-Method: POST' 
-H 'Origin: http://localhost:3000' 
-H 'Accept-Encoding: gzip, deflate, br' 
-H 'Accept-Language: en-US,en;q=0.9' 
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36' 
-H 'Accept: */*' 
-H 'Connection: keep-alive' 
-H 'Access-Control-Request-Headers: authorization,content-type' 
--compressed


curl 'http://127.0.0.1:8000/api/stores/csv' 
-H 'Origin: http://localhost:3000' 
-H 'Accept-Encoding: gzip, deflate, br' 
-H 'Accept-Language: en-US,en;q=0.9' 
-H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEwNCwiaXNzIjoiaHR0cDpcL1wvMTkyLjE2OC4wLjIzMjo4MDAwXC9hcGlcL3VzZXJzXC9sb2dpbiIsImlhdCI6MTUxOTk2OTAzNiwiZXhwIjoxNjE0NTc3MDM2LCJuYmYiOjE1MTk5NjkwMzYsImp0aSI6IndHV0UzRjhYQ3hRdDBGOWMifQ.XqySEIprbxtAU-RfhOgtFkScN1nUuuXEwMxCltfjqu8' 
-H 'Content-Type: application/json' 
-H 'Accept: application/x.toters.v1+json' 
-H 'Referer: http://localhost:3000/?local/' 
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36' 
-H 'Connection: keep-alive' 
--data-binary $'------WebKitFormBoundary9ApCHw2ykmLYK2IY\r\nContent-Disposition: form-data; name="file"; filename="bac-383-store-update.csv"\r\nContent-Type: text/csv\r\n\r\n\r\n------WebKitFormBoundary9ApCHw2ykmLYK2IY--\r\n' --compressed

restangular/chrome server logs

[2018-03-03 06:34:52] local.INFO: ----------------------------- [] []
[2018-03-03 06:34:52] local.INFO: OPTIONS api/stores/csv [] []
[2018-03-03 06:34:52] local.INFO: array ( ) [] []
[2018-03-03 06:34:52] local.INFO: Status code: 200 [] []
[2018-03-03 06:34:52] local.INFO: ----------------------------- [] []
[2018-03-03 06:34:52] local.INFO: POST api/stores/csv [] []
[2018-03-03 06:34:52] local.INFO: array ( ) [] []
[2018-03-03 06:34:52] local.INFO: Status code: 200 [] []
[2018-03-03 06:34:52] local.INFO: User id: 104 [] []

update 2:

after comparing the headers between both curls, i noticed that the content type was different:

postman curl snippet

-H 'Content-Type: application/x-www-form-urlencoded' \

restangular curl snippet

-H 'Content-Type: application/json' 

this was shocking, considering that the rectangular people PROMISED that by using the above syntax, the content type should be application/x-www-form-urlencoded:

Restangular.all('users') .withHttpConfig({transformRequest: angular.identity}) .customPOST(formData, undefined, undefined, { 'Content-Type': undefined }); This basically tells the request to use the Content-Type: multipart/form-data as the header.

so I wrote this:

    API.all('stores/csv').withHttpConfig({transformRequest: angular.identity})
    .customPOST(formData, undefined, undefined,
      { 'Content-Type': 'application/x-www-form-urlencoded' }).then((response) => {console.log(response);

this improved things a bit.. compare the two curls now:

postman

curl -X POST \
  http://127.0.0.1:8000/api/stores/csv \
  -H 'Accept: application/x.toters.v1+json' \
  -H 'Authorization: Bearer ***' \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Postman-Token: 4f9d2f3b-551b-aa47-4f65-98c7582f2919' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F file=@/Users/Shared/Download/bac-383-store-update.csv

angular

  curl 'http://127.0.0.1:8000/api/stores/csv' 
  -H 'Origin: http://localhost:3000' 
  -H 'Accept-Encoding: gzip, deflate, br' 
  -H 'Accept-Language: en-US,en;q=0.9' 
  -H 'Authorization: Bearer ***
  -H 'Content-Type: application/x-www-form-urlencoded' 
  -H 'Accept: application/x.toters.v1+json' 
  -H 'Referer: http://localhost:3000/?local/' 
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36' 
  -H 'Connection: keep-alive' 
  --data $'------WebKitFormBoundaryd405EnTxpFJv2GDN\r\nContent-Disposition: form-data; name="file"; filename="bac-383-store-update.csv"\r\nContent-Type: text/csv\r\n\r\n\r\n------WebKitFormBoundaryd405EnTxpFJv2GDN\r\nContent-Disposition: form-data; name="name"\r\n\r\nfile\r\n------WebKitFormBoundaryd405EnTxpFJv2GDN--\r\n' 
  --compressed

so i'm still not sending the -F option

1
  • I'm not sure what arguments customPOST takes, but have you tried customPOST(formData, undefined, undefined, ...) using undefined instead of an empty string, or 'file' as the second argument? Also, this example may help github.com/mgonto/restangular/issues/… Commented Mar 3, 2018 at 15:26

2 Answers 2

3

I've not touched on restangular before, however in Laravel, when you want to get a file from the request you need to use the file method on the request object:

$file = $request->file('file');

That should give you an instance of Illuminate\Http\UploadedFile

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

1 Comment

that didn't make a difference
1

I haven't delved into restangular a lot but on an HTTP level, I believe you want your Content-Type header to be multipart/form-data, not application/x-www-form-urlencoded.

If you're curious about the difference, check this answer out.
Since you're sending a file, multipart/form-data is what you want.


I know you see Postman do:

-H 'Content-Type: application/x-www-form-urlencoded'

But just a few lines under that, it does:

-H 'content-type: multipart/form-data; boundary...

4 Comments

What's the difference between upper case and lower case content-type?
@abbood: Nothing, HTTP headers are case-insensitive (Source)
So then how did it make sense that the same request has two different values for the same header?
HTTP Requests can have duplicate headers. It makes sense for things like Cache-Control or Cookie, but doesn't much for Content-Type. So I'm guessing web servers just handle it by using the last specified value of the header. Not sure why postman is putting the same header twice though here, might be worth a PR to fix it :)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.