Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with file download on iOS #623

Open
3 tasks done
kunalSBasic opened this issue May 21, 2024 · 4 comments
Open
3 tasks done

Issue with file download on iOS #623

kunalSBasic opened this issue May 21, 2024 · 4 comments

Comments

@kunalSBasic
Copy link

kunalSBasic commented May 21, 2024

Bug Report

Problem

I'm encountering an issue with the cordova-plugin-file plugin in iOS when trying to download and save a PDF file from an API response. The plugin seems to be working fine in Android, but I'm facing difficulties in iOS.

What is expected to happen?

The PDF file should be successfully downloaded and saved to the device's filesystem in iOS, similar to how it's functioning in Android.

What does actually happen?

Code runs successfully and falls under the success block and even present the toast of 'File downloaded successfully.' But file is not downloaded on device.

Information

Command or Code

downloadPdfMobile(base64Data, fileName) {
   const folderPath = this.platform.is('android')
     ? this.file.externalRootDirectory + 'Download/'
     : this.file.documentsDirectory;

   console.log(folderPath, 'FOLDERPATH');

   // Convert base64 to Blob
   const byteCharacters = atob(base64Data);
   const byteNumbers = new Array(byteCharacters.length);
   for (let i = 0; i < byteCharacters.length; i++) {
     byteNumbers[i] = byteCharacters.charCodeAt(i);
   }
   const byteArray = new Uint8Array(byteNumbers);
   const blob = new Blob([byteArray], { type: 'application/pdf' });

   // Write the file
   this.file
     .writeFile(folderPath, fileName, blob, {
       replace: true,
     })
     .then(() => {
       this.presentToast('File downloaded successfully.');
       console.log('File downloaded successfully.');
     })
     .catch((error) => {
       this.presentToast('Error while downloading the file:');
       console.error('Error while downloading the file:', error);
     });
 }

Environment, Platform, Device

Version information

Cordova Version: 12.0.0

Checklist

  • I included all the necessary information above
  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
@breautek
Copy link
Contributor

Code runs successfully and falls under the success block and even present the toast of 'File downloaded successfully.' But file is not downloaded on device.

This suggest that your writeFile api is perhaps resolving too early at:

this.file
     .writeFile(folderPath, fileName, blob, {
       replace: true,
     })

Please show the implementation of this method, or the method that makes use of cordova's plugin write API.

@kunalSBasic
Copy link
Author

@breautek Sure here's the entire implementation.

So I have a component called orderList in which I have a button which is

          <div style="text-align: end">
            <ion-icon
              class="downloadIcon"
              (click)="fetchPDF(item.id, item.performaNo, item.orderNo)"
              name="cloud-download-outline"
              slot="icon-only"
            ></ion-icon>
          </div>

Here's the fetchPDF method:

  fetchPDF(invoiceId, proformaNo, orderNo) {
    let ID = proformaNo ? proformaNo : orderNo;
    let name = `${ID}_${Date.now()}.pdf`;
    this.service
      .downloadProformaOrderPDF(invoiceId, this.tenantId)
      .subscribe((result) => {
        this.base64PdfDownload.downloadPDF(result['file'], name);
      });
  }

Once I fetch the pdf then I call the method downloadPDF by importing the service base64PdfDownload, of which the code is given below:

import { Injectable } from '@angular/core';
import { Platform } from '@ionic/angular';
import { File } from '@ionic-native/file/ngx';
import { ToastController } from '@ionic/angular';

@Injectable({
  providedIn: 'root',
})
export class Base64pdfdownloadService {
  constructor(
    private file: File,
    private platform: Platform,
    public toastController: ToastController
  ) {}

  downloadPDF(base64Data: string, fileName: string) {
    if (this.platform.is('cordova')) {
      // For mobile devices using Cordova File plugin
      this.downloadPdfMobile(base64Data, fileName);
    } else {
      // For web browsers
      this.downloadPdfWeb(base64Data, fileName);
    }
  }

  downloadPdfMobile(base64Data, fileName) {
    const folderPath = this.platform.is('android')
      ? this.file.externalRootDirectory + 'Download/'
      : this.file.documentsDirectory;

    console.log(folderPath, 'FOLDERPATH');

    // Convert base64 to Blob
    const byteCharacters = atob(base64Data);
    const byteNumbers = new Array(byteCharacters.length);
    for (let i = 0; i < byteCharacters.length; i++) {
      byteNumbers[i] = byteCharacters.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);
    const blob = new Blob([byteArray], { type: 'application/pdf' });

    // Write the file
    this.file
      .writeFile(folderPath, fileName, blob, {
        replace: true,
      })
      .then(() => {
        this.presentToast('File downloaded successfully.');
        console.log('File downloaded successfully.');
      })
      .catch((error) => {
        this.presentToast('Error while downloading the file:');
        console.error('Error while downloading the file:', error);
      });
  }

  downloadPdfWeb(base64Data: string, fileName: string) {
    // Convert base64 to Blob
    const byteCharacters = atob(base64Data);
    const byteNumbers = new Array(byteCharacters.length);
    for (let i = 0; i < byteCharacters.length; i++) {
      byteNumbers[i] = byteCharacters.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);
    const blob = new Blob([byteArray], { type: 'application/pdf' });

    // Create download link
    const link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = fileName;

    // Trigger download
    link.click();
  }

  async presentToast(message) {
    const toast = await this.toastController.create({
      message: message,
      duration: 2000,
      color: 'dark',
    });
    toast.present();
  }
}

@breautek
Copy link
Contributor

None of that shows what I asked for, which is the implementation that uses the cordova API. All code that was provided appears to be ionic's framework usage. Apache cannot provide support on framework code as that's not a code base that is maintained by Apache.

You may need to create a sample reproduction application application that uses the cordova file plugin directly that demonstrates your issue so that we can eliminate and isolate the issue away from any app or framework code.

@kunalSBasic
Copy link
Author

##560 (comment)
##343

The above issues are similar to mine and has a working solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants