15

Ok, so I try to read a PDF file like this:

reader.readAsArrayBuffer(file);

and then try to send it to the server using $http like this:

$http.put(url, data, {headers: {'Content-Type': 'application/pdf'}});

So, just read & send the binary to the server in raw form. According to some resources I found, passing an ArrayBuffer to XHR should work, but passing it as data to $http just results in a request body like this: {} and Content-Length=2

Reading the file readAsBinaryString() results in a corrupted file (and is apparently deprecated for that very reason)

The use case seems so trivial to me, am I missing something?

Chrome 36, Angular 1.2.20

joerx
  • 2,028
  • 1
  • 16
  • 18

3 Answers3

32

You have to use reader.readAsArrayBuffer(file); then in the onload callback create an ArrayBufferView from the result:

new Uint8Array(reader.result)

pass that data to $http and overwrite the transformRequest property so angularjs doesn't encode your array into json:

reader.onload = function() {
    $http({
        method: 'PUT', 
        headers: {'Content-Type': 'application/pdf'}, 
        data: new Uint8Array(reader.result), 
        transformRequest: []
    })
};
reader.readAsArrayBuffer(file);
joerx
  • 2,028
  • 1
  • 16
  • 18
timbz
  • 346
  • 2
  • 3
  • 3
    Is it just standard behaviour for AngularJS to encode everything into json? I don't see why one would encode byte arrays as json data. – Kristian Barrett Aug 06 '14 at 13:13
  • 3
    @tbaetz: I was banging my head for almost two days with it... Thanks for that answer. – jjczopek Mar 28 '15 at 10:07
  • 1
    @tbaetz: Half a day of work, and finally saved by your solution. You're great, man. – blas3nik Sep 24 '15 at 12:13
  • What about passing other parameters/metadata into the WebAPI method besides the binary? My method takes the PDF byte array as just one of several parameters it needs. – Mike K Jan 09 '18 at 19:46
1

Is it because you are just handing the $http method the array buffer instead of writing that buffer into a byte array? If so what you are posting to the server is probably just the arraybuffer object.

Check this post on how to write ArrayBuffer to byte array: How do I read binary data to a byte array in Javascript?

Community
  • 1
  • 1
Kristian Barrett
  • 3,574
  • 2
  • 26
  • 40
0

There are two problems in your request.

  1. You need to supply a data view to $http function.

So, data should be new DataView(data) or new Uint8Array(data) etc

  1. $http always attempt to send the data as json. You can prevent this if you override the transform function. The transform function is the agent that is responsible for transforming your binary into json.

So, you should add transformRequest: [] property to your request.

Example:

var request = $http({
                        method: 'PUT',
                        url: 'example.com',
                        data: new Uint8Array(data),
                        headers: {'Content-Type': 'application/octet-stream'},  
                        transformRequest: [],
                        responseType: 'arraybuffer'
                    });
Charlie
  • 22,886
  • 11
  • 59
  • 90