admin管理员组

文章数量:1393866

I am trying to download a file using FileSaver.js, but I get a corrupted file whenever I hit download button.

App is backed by a PHP REST service, and using cURL from mand line confirms that REST is working OK.

Here is last version of pseudo-code that I use for downloading:

// Let str be the data received from $http promise
// This code is run in a "then" callback

var arr= new Uint8Array(str.length);
for(var i=0; i<str.length; i++) {
    arr[b]=str.charCodeAt(i);
};
var blob = new Blob([arr], {type: 'application/octet-stream'});
saveAs(blob, "AFileName");

It just corrupts file.

I also tried without applying the Uint8Array, and giving str directly to Blob. As you guessed, it failed too.

I am writing server and client myself, so I can change anything in them. But the thing is I want to handle downloads client-side, and I just can't redirect users to file URL to download it, because REST needs authentication and that token only lives within Angular app. It would not be a good choice to change server just to handle file downloads without authentication.

The REST has URLs like /files/:id that when accessed, gives file content as a regular HTTP file download (tested with cURL as said above). Could $http be the problem? Somehow forcing some kind of encoding or some assumptions on received data. I don't have much experience in Angular, anyway.

I am trying to download a file using FileSaver.js, but I get a corrupted file whenever I hit download button.

App is backed by a PHP REST service, and using cURL from mand line confirms that REST is working OK.

Here is last version of pseudo-code that I use for downloading:

// Let str be the data received from $http promise
// This code is run in a "then" callback

var arr= new Uint8Array(str.length);
for(var i=0; i<str.length; i++) {
    arr[b]=str.charCodeAt(i);
};
var blob = new Blob([arr], {type: 'application/octet-stream'});
saveAs(blob, "AFileName");

It just corrupts file.

I also tried without applying the Uint8Array, and giving str directly to Blob. As you guessed, it failed too.

I am writing server and client myself, so I can change anything in them. But the thing is I want to handle downloads client-side, and I just can't redirect users to file URL to download it, because REST needs authentication and that token only lives within Angular app. It would not be a good choice to change server just to handle file downloads without authentication.

The REST has URLs like /files/:id that when accessed, gives file content as a regular HTTP file download (tested with cURL as said above). Could $http be the problem? Somehow forcing some kind of encoding or some assumptions on received data. I don't have much experience in Angular, anyway.

Share Improve this question edited Oct 10, 2015 at 19:18 vfsoraki asked Oct 10, 2015 at 7:27 vfsorakivfsoraki 2,3271 gold badge22 silver badges47 bronze badges 2
  • @ArtjomB Is saying "Thanks" against rules here? – vfsoraki Commented Oct 10, 2015 at 18:15
  • You could say that: Should 'Hi', 'thanks,' taglines, and salutations be removed from posts?, but don't go and remove these things from old post. That might give them unwanted attention. Also, when you go about doing this, you should fix everything in the post. The reason I did this edit was because another user suggested the PHP tag for your question which seemed wrong since you've said you tested that part and it works. I then rejected their edit with an edit of my own. – Artjom B. Commented Oct 10, 2015 at 18:51
Add a ment  | 

1 Answer 1

Reset to default 8

I have found the problem. It was me :)

I had to specify responseType: "arraybuffer" for $http then give str directly to Blob.

Fixed code

// Let str be the data received from $http promise
// This code is run in a "then" callback
// Make sure to specify "responseType: "arraybuffer"" for $http

var blob = new Blob([str], {type: 'application/octet-stream'});
saveAs(blob, "AFileName");

I was changing responseType in wrong place.

本文标签: javascriptCorrupted download in AngularJs appStack Overflow