javascriptangulartypescriptios-web-apppkpass

is there is any way possible to download multiple files(.pkpass) on iphone?


I am trying to download multiple boarding passses in ios using blob.

initially I am using this

private downloadMultipleFiles(boardingPassURLs : string[]): void{
    boardingPassURLs.forEach((url) => {
      this.downloadFileService.downloadFileFromURL(url).subscribe((blob) => {
        const a = document.createElement('a');
        const objectUrl = URL.createObjectURL(blob);
        a.href = objectUrl;
        a.download = 'filenameXYZ.pkpass';
        a.click();
        URL.revokeObjectURL(objectUrl);
      });
    });
    this.loaderService.setIsLoaderVisible(false);
  }

  downloadFileFromURL(url: string) {
    return this.http.get(url, { responseType: 'blob' });
  }

It works on windows for all browsers. But when i chcecked iphone in safari it says

"Safari can not download this file."

I have tried these approaches which is mentioned below but it did'nt worked out either.

  1. Tried with adding timeouts
  private downloadMultipleFiles(boardingPassURLs : string[]): void{
    boardingPassURLs.forEach((url) => {
      setTimeout(() => {
        this.downloadFileService.downloadFileFromURL(url).subscribe((blob) => {
          const a = document.createElement('a');
          const objectUrl = URL.createObjectURL(blob);
          a.href = objectUrl;
          a.download = 'filenameXYZ.pkpass';
          a.click();
          URL.revokeObjectURL(objectUrl);
        });
      },500);
    });
    this.loaderService.setIsLoaderVisible(false);
  }
  1. Added MIME content Type
private downloadMultipleFiles(boardingPassURLs: string[]): void {
    boardingPassURLs.forEach((url, index) => {
      setTimeout(() => {
        this.downloadFileService.downloadFileFromURL(url).subscribe((blob) => {
          const modifiedBlob = new Blob([blob], { type: 'application/octet-stream' });
          const objectUrl = URL.createObjectURL(modifiedBlob);
          const a = document.createElement('a');
          a.href = objectUrl;
          a.download = 'filenameXYZ.pkpass';
          a.click();
          URL.revokeObjectURL(objectUrl);
        });
      }, index * 500);
    });
    this.loaderService.setIsLoaderVisible(false);
  }

  downloadFileFromURL(url: string) {
    const headers = new HttpHeaders({
      Accept: 'application/octet-stream',
    });

    return this.http.get(url, { headers,responseType: 'blob' });
  }

In this scenario only the initial file was downlaoding, and that too was blank.

  1. Tried MIME Type - 'application/vnd.apple.pkpass' But it gaves the same error as > "Safari can not download this file."

  2. Tried using Iframes

private downloadMultipleFiles(boardingPassURLs: string[]): void {
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    document.body.appendChild(iframe);
  
    boardingPassURLs.forEach((url, index) => {
      setTimeout(() => {
        this.downloadFileService.downloadFileFromURL(url).subscribe((blob) => {
          const objectUrl = URL.createObjectURL(blob);
  
          const a = iframe.contentWindow?.document.createElement('a');
          if (a) {
            a.href = objectUrl;
            a.download = 'filenameXYZ.pkpass';
            a.click();
          }
  
          URL.revokeObjectURL(objectUrl);
        });
      }, index * 500);
    });
    this.loaderService.setIsLoaderVisible(false);
  }

It did'nt worked either.


Solution

  • I tried using the below MIME type and added delay between each download and it's working fine.

    "application/vnd-com.apple.pkpass"

    private downloadMultipleFiles(boardingPassURLs: string[]): void {
        const downloadObservables = boardingPassURLs.map((url) =>
          this.downloadFileService.downloadFileFromURL(url).pipe(
            map((blob) => {
              const modifiedBlob = new Blob([blob], { type: 'application/vnd-com.apple.pkpass' });
              const objectUrl = URL.createObjectURL(modifiedBlob);
              const a = document.createElement('a');
              a.href = objectUrl;
              a.download = `FilenameXYZ.pkpass`;
              a.click();
              URL.revokeObjectURL(objectUrl);
            }),
            delay(500),
          ),
        );
      
        of(...downloadObservables).pipe(
          concatMap((download$) => download$),
        ).subscribe({
          error: (err) => {
            console.error('Error downloading file:', err);
                this.loaderService.setIsLoaderVisible(false);
          },
          complete: () => {
                this.loaderService.setIsLoaderVisible(false);
          },
        });
      }