2

I am uploading a file through an API call that requires putting the file inside the Request body and using PUT. Using the following code, I am able to upload something that creates the file and returns a 200 status. The rawData length is exactly the length expected based on the initial file size. However, the files created have some additional bytes and cannot be opened. For example, a jpg file I upload at 234 kb has 352 kb after upload, while a docx file starting at 12 kb has 17 kb after upload.

        var contentType = file.type;
        var reader = new FileReader();
        reader.onload = function (e) {
            var rawData = reader.result;

            $http({
                url: appSettings.serverPath + '/File/' + fileId + '/Content',
                method: 'PUT',
                headers: { 'Content-Type': undefined },
                data: rawData,
                transformRequest: []
            }).success(function (data, status, headers, config) {
                deferred.resolve(data);
            }).error(function (error) {
                deferred.reject(error);
            });

        };

        reader.readAsBinaryString(file);

Besides using 'Content-Type' of undefined, I have used the content type of the file, but I have the same issue.

I have tried calling the readAsArrayBuffer method on the FileReader and passing in a Uint8Array of the rawData, but that does not pass in any data on the Request and creates a file with 0 bytes.

I have also tried calling the readAsDataURL method on the FileReader, which encodes the data completely differently such that my rawData and resulting file are 313 kb for the jpg. The file is still corrupted and cannot be opened.

Is there some additional encoding, etc., that I should be doing to send the correct data?

Thanks in advance!!

ChristyPiffat
  • 359
  • 1
  • 6
  • 26

1 Answers1

0

There is no need to use the FileReader API to read the file. The XHR Send Method automatically serializes file objects as they are a special type of Blob object.

    //var contentType = file.type;
    //var reader = new FileReader();
    //reader.onload = function (e) {
    //    var rawData = reader.result;

    return $http({
        url: appSettings.serverPath + '/File/' + fileId + '/Content',
        method: 'PUT',
        headers: { 'Content-Type': undefined },
        //data: rawData,
        data: file
        //transformRequest: []
    };
    /*  }).success(function (data, status, headers, config) {
            deferred.resolve(data);
        }).error(function (error) {
            deferred.reject(error);
        });
    */

    //reader.readAsBinaryString(file);

Also there is no need to manufacture a promise with $q.defer as the $http service already returns a promise.

Also the .success and .error methods are deprecated and removed from Angular V1.6.


FileReader.readAsBinaryString() Deprecated

The rawData length is exactly the length expected based on the initial file size. However, the files created have some additional bytes and cannot be opened. For example, a jpg file I upload at 234 kb has 352 kb after upload, while a docx file starting at 12 kb has 17 kb after upload.

//reader.readAsBinaryString(file);

reader.readAsArrayBuffer(file)

The XHR Send Method converts binary strings (DOMstring) to UTF-8. This means that data bytes in the range 128-255 are encoded with 2 bytes. Don't convert binary data to DOMstrings. Use the ArrayBuffer API.

FileReader.readAsBinaryString()

Non-standard

This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

[It] is now deprecated as per the 12 July 2012 Working Draft from the W3C.

— MDN Developer Reference - Web APIs - FileReader.readAsBinaryString()

Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95