Search code examples
androidangularnativescriptblob

nativescript saving a blob error Cannot convert object to [B at index 1


I've got a Nativescript Angular app which downloads a pdf from a Rails server as a Blob Uint8Array format and when I try and save it I get the following error;

JS: /data/user/0/com.asset.management/files/result.pdf
JS: ERROR Error: Uncaught (in promise): Error: Cannot convert object to [B at index 1
JS: Error: Cannot convert object to [B at index 1
JS:     at file: node_modules/@nativescript/core/file-system/file-system-access.android.js:215:0
JS:     at new ZoneAwarePromise (file: node_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:902:0)
JS:     at FileSystemAccess.push.../node_modules/@nativescript/core/file-system/file-system-access.js.FileSystemAccess.writeAsync (file: node_modules/@nativescript/core/file-system/file-system-access.android.js:213:0)
JS:     at file: node_modules/@nativescript/core/file-system/file-system.js:240:0
JS:     at new ZoneAwarePromise (file: node_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:902:0)
JS:     at File.push.../node_modules/@nativescript/core/file-system/file-system.js.File.write (file: node_modules/@nativescript/core/file-system/file-system.js:231:0)
JS:     at SafeSubscriber._next (file: src/app/assets/assets.component.ts:92:25)
JS:     at SafeSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUn...

Here is the code;

        this.http.get(url, { responseType: 'blob' })
            .subscribe(data => {

                const documentsFolder = knownFolders.documents();
                const destination = path.join(documentsFolder.path, 'result.pdf');
                const file = File.fromPath(destination);

                file.write(data);
                this.pdfUrl = file.path;
            });

I'm trying to save the file so that I can view it with the nativescript-pdf-view plugin

Update: check file system

I've accessed my emulator and found the directory where it should be writing the file and it's there but it's zero bytes in size.

: adb root
: adb shell
: su
: cd /data/user/0/com.asset.management/files
: ls -al

Results
: -rw------- 1 u0_a78 u0_a78    0 2020-05-12 14:20 result.pdf

NOTE: I tried writting some basic text to a file and this worked. So it must have something to do with the format that the 'data' is in.

Update: results of 'data' in debugger

Blob {_buffer: Uint8Array(23251), _size: 23251, _type: "application/pdf", Symbol(Symbol.toStringTag): "Blob"}
size: 23251
type: "application/pdf"
Symbol(Symbol.toStringTag): "Blob"
_buffer: Uint8Array(23251) [37, 80, 68, 70, 45, 49, 46, 52, 10, 49, 32, 48, 32, 111, 98, 106, 10, 60, 60, 10, 47, 84, 105, 116, 108, 101, 32, 40, 254, 255, 41, 10, 47, 67, 114, 101, 97, 116, 111, 114, 32, 40, 254, 255, 0, 119, 0, 107, 0, 104, 0, 116, 0, 109, 0, 108, 0, 116, 0, 111, 0, 112, 0, 100, 0, 102, 0, 32, 0, 48, 0, 46, 0, 49, 0, 50, 0, 46, 0, 53, 41, 10, 47, 80, 114, 111, 100, 117, 99, 101, 114, 32, 40, 254, 255, 0, 81, 0, 116, 0, …]
_size: 23251
_type: "application/pdf"
__proto__: Object

Update: Created playground example

https://play.nativescript.org/?template=play-ng&id=gA70GM&v=2

Update: Sending on the backend

This is the Ruby on Rails code I use to send the test.pdf in the example. In my real application it's a generated pdf and not a file. The sending works the same though.

  def index

    respond_to do |format|
      format.html
      format.pdf do
        send_file("#{Rails.root}/public/test.pdf")
      end
    end
  end

Solution

  • I assume this is due to the Polyfills for Blob in {N}. You could convert the Blob object into Byte array.

       this.http.get(url, { responseType: 'blob' })
            .subscribe(data => {
    
                const documentsFolder = knownFolders.documents();
                const destination = path.join(documentsFolder.path, 'result.pdf');
                const file = File.fromPath(destination);
    
                const blob = (Array as any).create("byte", data.size);
                for (let i = 0; i < blob.length; i++) {
                    blob[i] = (data as any)._buffer[i];
                }
    
                file.write(blob);
                this.pdfUrl = file.path;
            });