5

I have a problem (or may be two) with saving files using HTML5 File API.

A files comes from the server as a byte array and I need to save it. I tried several ways described on SO:

  • creating blob and opening it in a new tab
  • creading a hidden achor tag with "data:" in href attribute
  • using FileSaver.js

All approaches allow to save the file but with breaking it by changing the encoding to UTF-8, while the file (in current test case) is in ANSI. And it seems that I have to problems: at the server side and at the client side.

Server side: Server side is ASP.NET Web API 2 app, which controller sends the file using HttpResponseMessage with StreamContent. The ContentType is correct and corresponds with actual file type.

But as can be seen on the screenshot below server's answer (data.length) is less then actual file size calculated at upload (file.size). Also here could be seen that HTML5 File object has yet another size (f.size).

Default file send

If I add CharSet with value "ANSI" to server's response message's ContentType property, file data will be the same as it was uploaded, but on saving result file still has wrong size and become broken:

enter image description here

Client side: I tried to set charset using the JS File options, but it didn't help. As could be found here and here Eli Grey, the author of FileUplaod.js says that

The encoding/charset in the type is just metadata for the browser, not an encoding directive.

which means, if I understood it right, that it is impossible to change the encoding of the file.

Issue result: at the end I can succeessfully download broken files wich are unable to open. The original and downloaded files

So I have two questions:

  1. How can I save file "as is" using File API. At present time I cannot use simple way with direct link and 'download' attribute because of serverside check for access_token in request header. May be this is the "bottle neck" of the problem?
  2. How can I avoid setting CharSet at server side and also send byte array "as is"? While this problem could be hacked in some way I guess it's more critical. For example, while "ANSI" charset solves the problem with the current file, WinMerge shows that it's encoding is cyrillic 'Windows-1251' and also can any other.

P.S. the issue is related to all file types (extensions) except *.txt.

Update

Server side code:

public HttpResponseMessage DownloadAttachment(Guid fileId)
{
    var stream = GetFileStream(fileId);

    var message = new HttpResponseMessage(HttpStatusCode.OK);
    message.Content = new StreamContent(stream);
    message.Content.Headers.ContentLength = file.Size;
    message.Content.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType)
        {
            // without this charset files sent with bigger size
            // than they are as shown on image 1
            CharSet = "ANSI"
        };
    message.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = file.FileName + file.Extension,
            Size = file.Size
        };

    return message;
}

Client side code (TypeScript):

/*
* Handler for click event on download <a> tag
*/
private downloadFile(file: Models.File) {
    var self = this;

    this.$service.downloadAttachment(this.entityId, file.fileId).then(
        // on success
        function (data, status, headers, config) {
            var fileName = file.fileName + file.extension;
            var clientFile = new File([data], fileName);
            // here's the issue ---^
            saveAs(clientFile, fileName);
        },
        // on fail
        function (error) {
            self.alertError(error);
    });
}

My code is almost the same as in answers on related questions on SO: instead of setting direct link in 'a' tag, I handle click on it and download file content via XHR (in my case using Angularjs $http service). Getting the file content I create a Blob object (in my case I use File class that derives from Blob) and then try to save it using FileSaver.js. I also tried approach with encoded URL to Blob in href attribute, but it only opens a new tab with a file broken the same way. I found that the probem is in Blob class - calling it's constructor with 'normal' file data I get an instance with 'wrong' size as could be seen on first two sceenshots. So, as I understand, my problem not in the way I try to save my file, but in the way I create it - File API

Nozim Turakulov
  • 769
  • 1
  • 8
  • 19
  • 1
    Is `data` an `ArrayBuffer` or binary string? – guest271314 May 12 '16 at 04:02
  • @guest271314 honestly, I don't know, but I guess it's a binary string – Nozim Turakulov May 19 '16 at 14:49
  • 1
    _"How can I save file "as is" using File API. At present time I cannot use simple way with direct link and 'download' attribute because of serverside check for access_token in request header."_ See http://stackoverflow.com/questions/13581157/ajax-file-download-with-custom-header/ Can you include text of `js` used and server-side proceses at Question?, instead of or below image? – guest271314 May 19 '16 at 14:56
  • @guest271314 thank you for your attension. I updated the question with code samples. Also I checked the `data` - it's typeof `string`. – Nozim Turakulov May 20 '16 at 08:23
  • _"So, as I understand, my problem not in the way I try to save my file, but in the way I create it - File API"_ You posted that you are creating `.txt` files for download, yet you describe broken image at after download? _"ssue result: at the end I can succeessfully download broken files wich are unable to open."_ Why are you attempting to set a character encoding http://stackoverflow.com/questions/701882/what-is-ansi-format on image file? – guest271314 May 20 '16 at 13:54
  • 1
    _"So, as I understand, my problem not in the way I try to save my file, but in the way I create it - File API"_ You posted that you are creating `.txt` files for download yet you describe broken image file after download? _"Issue result: at the end I can succeessfully download broken files wich are unable to open."_ Why are you attempting to set a character encoding stackoverflow.com/questions/701882/what-is-ansi-format on image file? Or, why did you include description of broken image downloads if you are only creating `.txt` files for download? What is `data` at `new File([data], fileName);` – guest271314 May 20 '16 at 14:01
  • @guest271314 Extension of downloading file can be any that user has uploaded. If I download simple text file (`.txt`) - everything works fine. If file is of any other extension - server sends data in UTF-8 encoding that differs from the original file on byte to byte comparison and have different size. This issue is shown in first image where `data.length` is less then `file.size`. I solved this problem with setting charset to `ANSI` so the downloaded file data is the same as it was uploaded - on the second image `file.size` is equals to `data.length`. And here we come to problem with Blob size – Nozim Turakulov May 21 '16 at 09:59
  • Still not grasping what issue is, here. Have not tried `asp.net-web-api` and not sure why you are setting charset to `ANSI`? Do not believe you need to set a charset at image files. – guest271314 May 21 '16 at 13:27

0 Answers0