(Cordova/Capacitor) Download a file from its app?
Asked Answered
A

1

7

Goal : My application creates a zip. User downloads it to their device.

Problem : It works perfectly with Electron and Browser, but with Android it doesn't work

Try 1 window.showSaveFilePicker()

      const fileHandle = await window.showSaveFilePicker({suggestedName: 'package.zip'});
      const writable = await fileHandle.createWritable();
      await writable.write(blob);
      await writable.close();

Opens a window to save the file. Works on Browser and Windows application. On Android, nothing happens.

Try 2 Download Link

      const downloadUrl = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href =  downloadUrl; 
      link.target= '_blank';
      link.download = 'package.zip';
      document.body.appendChild(link);
      link.click();

Opens a window to save the file. Works with Browser and Windows application. With Android, none. AndroidStudio Log : E/Capacitor: Unable to open asset URL

Try 3 Download Link with local file (Just to check)

<a href="/assets/imgs/pack.zip" download>DOWNLOAD</a>

Works with Browser and Windows application. With Android, nothing, same error.

Try 4 Alternative

const path = `${directory}/${name}`;
const blob = new Blob([file], {type: file.type});
const data = await this.blobToBase64(blob);
await Filesystem.writeFile({path, data, directory: Directory.Documents, encoding: Encoding.UTF8});

Use FileSystem (Directory.Documents) to save to user's device. I want to avoid, it's not user friendly and Doesn't work because the files are transformed to base64 to be used by the Android Filesystem API. They are unusable. :/

Additional info

AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>

package.json

"@capacitor/android": "^3.6.0",
"@capacitor/core": "^3.6.0",
"@capacitor/filesystem": "^1.1.0",
Artamas answered 22/7, 2022 at 15:24 Comment(1)
Are you using a framework maybe ? #70658443Confiscate
H
0

I managed to make it work with FileSharer plugin.

In my implementation, I retrieved the file through an HTTP request, but FileSharer also supports sharing files from a base64 source.

What it does is open a sharing popup that allows the user to save the file on filesystem or share it with other applications.

"@byteowls/capacitor-filesharer": "^4.0.0"

Here is my implementation:

openFile(params: { res: any; filename: string}) {
    const file = new Blob([params.res], {type: 'application/octet-stream'});
    if (!window.hasOwnProperty('cordova')) {
      // Web implementation
    } else {
      const reader = new FileReader();
      reader.onload = () => {
          const dataUrl: any = reader?.result;
          if (dataUrl) {
            const base64 = dataUrl.split(',')[1];
            FileSharer.share({
              filename: params.filename,
              base64Data:   base64,
              contentType: 'application/octet-stream',
            });
          }

      };
      reader.readAsDataURL(file);
    }
  }
Helianthus answered 30/6, 2023 at 15:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.