Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs file upload in put method not working

I have a simple todos application in which i am trying to upload a photo along with a single todo. Now i have created this factory function that takes care of the creation of the todo

  todosFactory.insertTodo = function(todo){
    return $http.post(baseUrl, todo, {
      headers: {
        'Content-Type' : undefined
      },
      transformRequest: function(data, headersGetter){
        var formData = new FormData();
        angular.forEach(data, function (value, key) {
            formData.append(key, value);
        });
        return formData;
      }
    });
  };

And the factory update method looks like this

  todosFactory.updateTodo = function(id, todo){
    return $http.put(baseUrl + '/' + id, todo, {
      headers: {
        'Content-Type' : undefined
      },
      transformRequest: function(data, headersGetter){
        var formData = new FormData();
        angular.forEach(data, function (value, key) {
            formData.append(key, value);
        });
        return formData;
      }
    });
  };

The insertTodo is working as expected but the updateTodo is not posting data to the server. I am using laravel for the API and the update API endpoint has this code

dd(Input::all(), Input::file('cover_photo'));

This shows that noting was posted in the request. And if i change the put to post in the updateTodo factory method it starts working. Am i missing some extra headers or something ?

Update

If i remove both the transformRequest and headers form the updateTodo method, the text data is successfully received on the server but the the file doesn’t.
And if i just remove the headers nothing gets posted

Update

I am using the PHP server that comes with laravel using this command

php artisan serve

Update

Thanks to @Ricardo's answer i was able to get the submitted data using this code

router->put('/todos/{id}', function($id){
    $stream = file_get_contents("php://input");
    echo $stream;
    die();
});

I am getting the stream in this format

-----------------------------3643739756006088191021064137
Content-Disposition: form-data; name="id"

5
-----------------------------3643739756006088191021064137
Content-Disposition: form-data; name="name"

Image Todo
-----------------------------3643739756006088191021064137
Content-Disposition: form-data; name="complete"

0
-----------------------------3643739756006088191021064137
Content-Disposition: form-data; name="created_at"

2015-10-02 06:28:10
-----------------------------3643739756006088191021064137
Content-Disposition: form-data; name="updated_at"

2015-10-02 06:28:10
-----------------------------3643739756006088191021064137
Content-Disposition: form-data; name="cover_photo"; filename="Dragon-Falls-Venezuela-5.jpg"
Content-Type: image/jpeg

�����JFIF��H�H������Exif��MM�*�����i������������������z���,����UNICODE��C�R�E�A�T�O�R�:� 
�g�d�-�j�p�e�g� �v�1�.�0� �(�u�s�i�n�g� �I�J�G� �J�P�E�G� �v�6�2�)�,� �q�u�a�l�i�t�y� �=� �9�0�

Now i need to parse this raw format. I have found two php methods that other people have suggested http://php.net/manual/en/function.mb-parse-str.php and http://php.net/manual/en/function.parse-str.php but both of them are not working properly and do not give an array like $_GET or $_POST.

like image 494
Sajjad Ashraf Avatar asked Oct 02 '15 07:10

Sajjad Ashraf


1 Answers

This piece from the PHP documentation discusses the PUT method and file uploads (multipart/form-data).

I can't quote any parts from it because I think everything is important. You should read it in detail but to summarize it's not possible without changes to your Apache configuration and creation of auxiliary scripts.

With Laravel you should use Form Method Spoofing (basically a variable called _method) and keep on using POST. The _method will allow you to call Laravel's PUT action correctly.


Edit

AngularJS, by default, sends data in the JSON format which explains why you cannot access the data with the $_POST global. I have answered this in another question which explains what you have to do.

like image 74
Ricardo Velhote Avatar answered Sep 28 '22 20:09

Ricardo Velhote