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 ?
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
I am using the PHP server that comes with laravel using this command
php artisan serve
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.
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.
我认为您必须在服务器端序列化文件,如果您发送文件然后附加自定义标头并在服务器端适当处理该标头请求。
Create you formData
upfront -> you don't need the transformer for that.
Add transformRequest : angular.identity
to your HTTP
headers. Your code should look similar to the snippet below:
$http.post('/api/endpoint', formData, {
transformRequest : angular.identity,
headers: {'Content-Type': undefined}
})
.success(function (data) {
// do stuff with data
})
.error(function (error) {
// recover from an error
});
Angular identity does nothing more than to spit back your form data: https://docs.angularjs.org/api/ng/function/angular.identity
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.