I'm having problems with angular file upload filename ecoding.
Example: uploading file žžž.txt. Result: žžž.txt
Relevent Html form parts:
<form id="fileupload"
action="/filestore/services/process/upload"
method="POST"
enctype="multipart/form-data"
data-ng-app="MyApp"
data-ng-controller="DemoFileUploadController"
data-file-upload="options"
<input type="file" name="files[]" multiple ng-disabled="disabled" file-change="uploadFile($event, files)">
File controller:
$scope.uploadFile = function($event, files) {
var file = files[0];
var data = new FormData();
console.log(file);
console.log(data);
data.append('file-0', file);
$.ajax({
url: uploadUrl,
data: data,
cache: false,
contentType: false,
processData: false,
type: 'post',
success: function(data) {
$scope.reload();
}
});
};
File object (printed by console.log(file)):
lastModified 1467975647307
lastModifiedDate Date {Fri Jul 08 2016 14:00:47 GMT+0300 (FLE Standard Time)}
name "žžž.txt"
size 7
type "text/plain"
Post request data body:
Source
-----------------------------2159279631001
Content-Disposition: form-data; name="file-0"; filename="žžž.txt"
Content-Type: text/plain
-----------------------------2159279631001--
As you can see from data/code, FormData is forming data object with incorrect filename, while File object itself is correct...any ideas why is that? How should I solve this?
Edit:
Request headers:
Content-Type multipart/form-data; boundary=---------------------------9275749615024
User-Agent Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
X-Requested-Wit XMLHttpRequest
Response headers:
Content-Length 337
Content-Type application/json;charset=UTF-8
Server Apache-Coyote/1.1
You should set the contentType and encoding on your ajax request.
$.ajax({
url: uploadUrl,
data: data,
cache: false,
contentType: "application/x-www-form-urlencoded;charset=UTF-8",
processData: false,
type: 'post',
success: function(data) {
$scope.reload();
}
});
note that you should change charset
To the specific charset you are using and wich contains ž
Also if you are using a backend. Make sure it uses the correct character encoding as well
UTF-8 should do the trick
Related
Using Angularjs 1.6.5 I am trying to upload a file to the Django server. When I try to upload the file I am not sure what type of 'Content-Type' header should be passed with the $http.patch method. Here is the following my Angular apps config:-
var app = angular.module("edit_modules", []);
app.config(function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common['Accept'] = 'application/json, text/javascript';
});
And this is my patch method:-
$http.patch(url, data, {
headers: {'Content-Type': 'application/json; charset=utf-8' }
}).then(successCallback, errorCallback);
function successCallback(response){
console.log("Success");
console.log(response);
};
function errorCallback(error){
alert("Error Uploading!");
console.log(error);
};
When I pass {'Content-Type': 'application/json; charset=utf-8' } through the Header I get the following error:-
"The submitted data was not a file. Check the encoding type on the form."
Status :- 400
Since its content-type is file I used the following header {'Content-Type': 'multipart/form-data; charset=utf-8'} . But then I got this error:-
Multipart form parse error - Invalid boundary in multipart: None
Status :- 400
As suggested in the link here I tried the following header as well {'Content-Type': undefined} But this as well did not resolve my problem and I got the following error:-
Unsupported media type "text/plain;charset=UTF-8" in request.
Status :- 415
However when I tried with simple text fields the PATCH method worked with the header supplied being {'Content-Type': 'application/json; charset=utf-8' }. I am not sure where the problem is. I even tried to see the console for what data was being set to be patched
data = {
"video": element.files[0]
};
console.log(data);
THIS is what i got on console:-
{video: File(99861)}video: File(99861) {name: "Capture2.PNG", lastModified: 1517491665223, lastModifiedDate: Thu Feb 01 2018 18:57:45 GMT+0530 (India Standard Time), webkitRelativePath: "", size: 99861, …}
any help is much appreciated.
Referring to the answer here I found that you need to attach the File Object to be sent using FormData. Also you need an additional header in config transformRequest: angular.identity,. Here is the successful PATCH method that worked for me.
var fd = new FormData();
fd.append('video', element.files[0]);
$http.patch(url, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(successCallback, errorCallback);
function successCallback(response){
console.log("Success");
console.log(response);
};
function errorCallback(error){
alert("Error Uploading!");
console.log(error);
};
In the second line 'video' is the REST API Endpoint's variable where my file will be stored. In order to avoid the error
Multipart form parse error - Invalid boundary in multipart: None
I have left the headers: {'Content-Type': undefined}.
Trying to have a zip file download in AngularJS I looked at AngularJS: download pdf file from the server and coded my controller as:
RolloutService.export(rollout.id, function(data, status, headers) {
var headers = headers();
var filename = headers['download-filename'] || 'file';
var octetStreamMime = 'application/octet-stream';
var contentType = headers['Content-Type'] || octetStreamMime;
if (navigator.msSaveBlob) {
var blob = new Blob([data], { type: contentType });
navigator.msSaveBlob(blob, filename);
} else {
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if (urlCreator) {
var link = document.createElement("a");
if ("download" in link) {
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
} else {
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
window.location = url;
}
}
}
});
But my file comes partly only.
Trying to unzip it gives:
stephane#stephane-ThinkPad-X60:~> unzip -l file
Archive: file
error [file]: missing 96319383 bytes in zipfile
(attempting to process anyway)
error [file]: start of central directory not found;
zipfile corrupt.
Note that if skipping the controller and going for a direct window.open() then the file comes complete and can be unzipped.
On the controller export request, the browser console shows the following headers:
Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/nitro-project-rest/rollouts/2/export
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en
Authorization:Basic bnNuQG5zbi5jb206ZXRvaWxl
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/34.0.1847.116 Chrome/34.0.1847.116 Safari/537.36
Response Headers
Access-Control-Allow-Headers:Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization
Access-Control-Allow-Methods:POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:http://localhost:9000
Access-Control-Max-Age:3600
Cache-Control:no-store
Cache-Control:no-cache
Content-Disposition:attachment; filename="Orange-rollout-rollout-export.zip"
Content-Length:1960
Content-Type:application/zip
Date:Wed, 05 Nov 2014 20:33:31 GMT
download-filename:Orange-rollout-rollout-export.zip
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Pragma:no-cache
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
My $http service was corrupting the file when sending the request.
I needed to add the following configuration:
responseType: 'arraybuffer'
as in:
factory.rolloutExport = function(rolloutId, successCallback, failureCallback) {
$http({
url: ENV.NITRO_PROJECT_REST_URL + '/rollouts/' + rolloutId + '/export',
method: 'GET',
responseType: 'arraybuffer',
cache: false,
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Authorization': AuthService.getCredentialsHeaders()
}
}).success(successCallback).error(failureCallback);
};
Now the zip file comes back untouched by any encoding converter.
I'm having trouble with an XHR Request, for some reason my server is not receiving my files:
Here is my angular service update algorithm:
var update = function(id, name, file) {
var formData = new FormData();
formData.append('name', name);
formData.append('img', file);
return $http({
method : 'PUT',
url : '/albums/' + id,
data : formData,
headers : {'Content-Type': undefined},
transformRequest : angular.identity
});
};
On my laravel controller I just have:
public function update($id) {
return Response::json(Input::hasFile('img'));
}
The file is obviously there, why can't I retrieve it in my backend?
This is my request info:
Remote Address:[::1]:8000
Request URL:http://localhost:8000/albums/1
Request Method:PUT
Status Code:200 OK
Request Headers
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,es;q=0.6
Cache-Control:no-cache
Connection:keep-alive
Content-Length:13811
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryJ46EVSBw57RaVu7x
Cookie:_token=eyJpdiI6IkkzSXVmdnhubFFlVnlzSnZNWVFzVWk3ZlVKSFRDNFFlNndJWUVsVGNVU2c9IiwidmFsdWUiOiI5OG5PamUrVGZkZGx0ajZONklWajJ2OTM3MWlRd2tGZ2g5S2Jja1RhVjJ4Q1wvYk9xQTB4TlRKUWxkWmdvRm1EcHlzTGRjSEdzN2U5TWNPYWxEYVExVUE9PSIsIm1hYyI6IjA4NTY0ZTlmMjAyNTk3NGQxMmFhODIxMTU3NGNiYjQ4ZDA3OTgxMTA3Yzk1MmVkNmJkMGNkYjUyMmNhMzZkNzQifQ%3D%3D; laravel_session=eyJpdiI6IjRISElnWjd3ZlwvY2k1Z1pvOERWOGxyVHlaQzEwRmlqY1FiV0tNNzZEbEs4PSIsInZhbHVlIjoiYnp4UzVqOFoxMm5MMXhQdzJhVFphSkgrRGh2b2plYXhjdXpTamJ0UjVYdGdxS0puQmpPVXhObEtyb1I3XC9HQnRFdnBMWXV0MzRmWXAybGRySGRvXC9vUT09IiwibWFjIjoiMGQ1NzUyYTBjZmU3NzQ3ZDBkYjg5ZWViOGZmYzg3ZDY1ODg0N2JmNDg1NmQyNmMwZDcxMDE5NzcxZjIxM2MxMiJ9
Host:localhost:8000
Origin:http://localhost:8000
Pragma:no-cache
Referer:http://localhost:8000/Admin/Client
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
Request Payload
------WebKitFormBoundaryJ46EVSBw57RaVu7x
Content-Disposition: form-data; name="name"
Some Weird Album
------WebKitFormBoundaryJ46EVSBw57RaVu7x
Content-Disposition: form-data; name="img"; filename="derpino.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryJ46EVSBw57RaVu7x--
Response Headers
Cache-Control:no-cache
Connection:close
Content-Type:application/json
Date:Wed, 29 Oct 2014 12:47:20 GMT
Host:localhost:8000
Set-Cookie:laravel_session=eyJpdiI6IlQ4WlFOaG1keVhXVlA1dlluNWFZZGlMcmRQNGM3bThCRjZ6cnh4ZlorcWs9IiwidmFsdWUiOiJOZkJXNXBJQTVSTGZzWHJ4alg1SXBoN0Q2ekR6UVpnWThKQ0c4MXZOQlc1RUhNMUUraUZSTlpPYTlPTFdLQXpiYTJONkRvb29WN1djVlZkSGdaWStjQT09IiwibWFjIjoiOWI5MzEwODE2YTZlM2EzODMwZDE1YzI4YmE4M2NiYWJjMTRjMDEzOGI3YjA4NmRlMGU5NDBlZWEyMzI4MGQ3MCJ9; path=/; httponly
X-Frame-Options:SAMEORIGIN
X-Powered-By:PHP/5.5.11
I found the error! Apparently I can not send a file with the PUT method, I changed the method to POST and It works. In both the service and the laravel route
var update = function(id, name, file) {
var formData = new FormData();
formData.append('name', name);
formData.append('img', file);
return $http({
method : 'PUT',
url : '/albums/' + id,
data : formData,
headers : {'Content-Type': undefined},
transformRequest : angular.identity
});
};
I have site.com.
Each request is redirected here (so 'site.com/book', 'site.com/settings' ecc.. point to 'site.com')
Then I have site.com/api/ where 'site.com/api/user', 'site.com/api/library/' ecc... are redirected.
I'm trying to use $http of AngularJS to request a JSON object to site.com/api.
On success, I receive status 200 but the response is the text/html of 'site.com/index.html'.
The headers sent with the request are:
Accept: "application/json, text/plain, /"
Content-Type: application/json;charset=utf-8
I tried to debug site.com/api/ with the app postman and it works as expected since I receive the correct JSON object.
I don't know if it is a problem of some .htaccess rule or the $routeProvider of AngularJS...
(I have a .htaccess file in 'site.com' and another one in 'site.com/api').
But I could be completely off the road. Maybe someone can help? Thanks.
var config = {method: 'POST', url: 'site.com/api/', data: $scope.data};
$scope.login = function(){
$http(config)
.success(function(resp, status, headers, config){
console.log(resp);
})
.error(function(resp, status, headers, config){
console.log(status);
});
};
Ok I tried again with a clearer mind this morning.
It seems that I was missing the http part of the url site.com/api/.
So it can work both with
var config = {method: 'POST', url: 'http://example.com/api/', data: $scope.data};
or
var config = {method: 'POST', url: '/api/', data: $scope.data};
I am new to azure blob storage and I am trying to upload image to blob storage. I am using angular at client end and uploaded image with following headers :
'Content-type'
'x-ms-blob-type'
'Content-Length'
my blob is saved and i can see it in Azure Portal. But I am not able to see images. I am unable to understand the reason.
Link of my client is http://educms.azurewebsites.net/#/pages/results
There is no button. as soon as you select an image file, it will get uploaded. You can see the uploaded file at https://hobcity.blob.core.windows.net/images2/filename.extension
Upload Code of AngularJs
$scope.uploadFile = function(files) {
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);
var size = files[0].size;
var name = files[0].name;
var type = files[0].type;
var postData = {"name" : name};
postData.containerName = 'images2';
DataService.save('/tables/results/', postData).then(function(data){
var header = {
'Access-Control-Allow-Origin': '*',
'Content-type' : type,
'x-ms-blob-type' : 'BlockBlob',
'Content-Length' : size
}
var url = data.imageUri
var queryString = data.sasQueryString
var uploadUrl = url+ '/' + name + '/?'+queryString
$http.put(uploadUrl, fd, {
headers: header,
transformRequest: angular.identity
}).success(function(data){
console.log(data)
}).error(function(err){
console.error(err);
});
});
}
HTML :
code can be seen live at http://educms.azurewebsites.net/scripts/controllers/results.js
Anyone know what's wrong ?
So I uploaded a simple text file and traced the request through Fiddler. Here's what I saw:
PUT http://hobcity.blob.core.windows.net/images2/simpletextfile.txt/?se=2014-08-11T17%3A13%3A52Z&sr=c&sp=w&sig=SlY7wURwfSjM72Hw22507OHpnaCC1Ky6POk6hhR6fbU%3D HTTP/1.1
Accept: application/json, text/plain, */*
Access-Control-Allow-Origin: *
Content-Type: text/plain, multipart/form-data; boundary=---------------------------7de26921205a0
x-ms-blob-type: BlockBlob
Referer: http://educms.azurewebsites.net/#/pages/results
Accept-Language: en-US
Origin: http://educms.azurewebsites.net
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: hobcity.blob.core.windows.net
Content-Length: 254
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
-----------------------------7de26921205a0
Content-Disposition: form-data; name="file"; filename="simpletextfile.txt"
Content-Type: text/plain
https://hobcity.blob.core.windows.net/images2/Add-Item.png
-----------------------------7de26921205a0--
I believe the reason you're running into the issue is because you're uploading the file as is (see your Content-Type is multipart/form-data) and this is corrupting the data. What you would need to do is read the file contents into a byte array and then upload that byte array. If you search for HTML 5 File API, you will find examples of how to read a file using JavaScript. Also I wrote a blog post about uploading files in Azure Blob Storage using JavaScript which you may find useful: http://gauravmantri.com/2013/12/01/windows-azure-storage-and-cors-lets-have-some-fun/ (though this post make use of jQuery instead of Angular but should give you some idea).