Capacitor: Support blob/large data

Created on 20 Nov 2018  路  9Comments  路  Source: ionic-team/capacitor

Investigate passing blobs from native to JS and vice versa.

enhancement

Most helpful comment

I've implemented this functionality as a plugin, see https://github.com/diachedelic/capacitor-blob-writer

All 9 comments

There is this issue about improvements and one of the is about blobs. Should we close this one or better to have an issue per improvement?
https://github.com/ionic-team/capacitor/issues/974

Great to see this on the roadmap. In the meantime, if working on a custom Capacitor plugin, are there any creative workarounds that might allow returning a blob/binary data without having to convert to JSON? Based on https://capacitor.ionicframework.com/docs/plugins/ios, it seems like the CAPPluginCall can only handle JSON right now, and that no amount of creative plugin writing could respond with a blob directly. Is that right?

The background here is that we're trying to let the user import and upload 20MB PDF files with our app. The current workaround is converting the binary data to base64 using FileSystem.readFile, and then converting it back to a blob in the app, and uploading to a remote server as XHR. Trying to avoid memory issues, and unable to do a direct Fetch on a non-HTTP URI (e.g. file://etc on iOS). Thanks

Fetch should work, but you have to use convertFileSrc on the file:// url

@jcesarmobile thank you! I was using convertFileSrc while running ng serve and getting a CORS error on the "capacitor://localhost" URL, but I see now that fetch is working with convertFileSrc on a production build. For ng serve, after doing convertFileSrc, replacing "capacitor://localhost" with window.location.origin gave me a URL that works just fine for fetch. Appreciate the quick help.

Sharing my workaround with you.

I'm using web-implementation of the Filesystem plugin.
Don't know if it's a good solution but it helps solving my problem.

import { FilesystemDirectory, FilesystemEncoding } from '@capacitor/core'
// const { Filesystem } = Plugins // => Doesn't work with blob in native
// Workaround: Use Web-Implementation of plugin
import { FilesystemPluginWeb } from '@capacitor/core/dist/esm/web/filesystem.js'
const Filesystem = new FilesystemPluginWeb()

I was able to create a service for writing and reading large blobs. (For web, blobs are already supported for indexeddb)

Reading is simply done with a fetch call.

Writing is a bit more tricky because we can only pass strings to that native layer.

Converting a large blob to a base64 string will crash the webview because the size is simply to big to handle. However we can split the blob into chunks and convert these smaller chunks to a base64 string. Then we can just use appendFile to stitch it back together.

@jcesarmobile

Would it be possible to integrate this into the Filesystem plugin so it is supported directly? Would you consider a the PR if I make one? Or is there a better solution?

I just had an idea of how we could theoretically stream large amounts of binary data directly to the filesystem from the webview. We could avoid the strings-only bridge by making a POST request which is intercepted by Capacitor, and the body written to disk. This could either be implemented within Filesystem.writeFile and Filesystem.appendFile, and/or be exposed as an HTTP endpoint like so:

const res = await fetch('https://stuff.com/video.mp4')
const myVideoBlob = await res.body()

// write options like `recursive` could be passed in this query string?
const writeUrl = '/_capacitor_file_/data/user/0/com.example.app/files/videos/1.mp4?recursive=true'

await fetch(writeUrl, {
  method: 'POST',
  body: myVideoBlob,
})

Thoughts?

I've implemented this functionality as a plugin, see https://github.com/diachedelic/capacitor-blob-writer

Blob writer plugin looks like an elegant solution, impressive benchmarks. Thanks @diachedelic for sharing!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

peterpeterparker picture peterpeterparker  路  3Comments

json-derulo picture json-derulo  路  3Comments

stripathix picture stripathix  路  3Comments

gnesher picture gnesher  路  3Comments

MatanYadaev picture MatanYadaev  路  3Comments