1

I created a function for downloading and saving the blob images so that if the user is offline, the images can still be rendered. I have to do it this way as the products are managed via a CMS.

Here is the function:

downloadProductImages(products) {
  return new Promise((resolve, reject) => {
    this.platform.ready()
      .then(() => {
        for (let i = 0; i < products.length; i++) {
          const productImageUrl = SERVER_URL + products[i].imageUrl,
                fileName = products[i].image;
          this.http
            .sendRequest(productImageUrl, {
              method: 'download',
              filePath: this.directoryPath + fileName,
              responseType: 'blob'
            })
            .then((response: any) => {
              this.file.writeFile(this.directory, fileName, response, {replace: true})
                .then(_ => {
                  resolve();
                })
                .catch(error => {
                  reject();
                });
            })
            .catch(error => {
              reject();
            });
        }
      });
  });
}

Here is the page view I would like the images to render:

<div [ngStyle]="{'background-image': 'url(\'' + (productImage !== '' ? productImage : '../../assets/images/image-not-available.png' | sanitizeUrl) + '\')'}">
  <ion-row>
    <ion-col size="12" size-sm="6">
      <div class="show-mobile">
        <img [src]="(productImage !== '' ? productImage : '../../assets/images/image-not-available.png' | sanitizeUrl)" class="img-responsive">
      </div>
    </ion-col>
  </ion-row>
</div>

1 Answers1

0

File API in a browser context is mostly built around "read" use case. Writing files to client machine is subject to security concerns and there is no seamless API to do that on client side.

So the approach you can take here is:

  • Store images' blobs using Ionic Storage (localForage does support storing blobs in indexeddb)
  • at application start check stored blobs and recover local cache by running forEach loop and create blobUrls
  • create condition for your img elements to read from local blobUrl if the app is offline

Directionally something like this below would be your main function:

async cacheImagesLocally() {

    // not sure what your products array looks like, but just for example here:
    const products = [{
      image: "image0",
      imageUrl: "someURL"
    }];

    // this one should probably be a property in your class:
    const localBlobUrlsCache = [];

    for (const product of products) {

      let localBlob = await this.storage.get(product.image);

      if (!localBlob) {

        const productImageUrl = SERVER_URL + product.imageUrl;
        const fileName = product.image;

        localBlob = await this.http.sendRequest(productImageUrl, {
          method: 'download',
          filePath: this.directoryPath + fileName,
          responseType: 'blob'
        });

      };

      localBlobUrlsCache.push({image: product.image, blobUrl: URL.createObjectURL(localBlob)});

    };

  };
Sergey Rudenko
  • 8,809
  • 2
  • 24
  • 51
  • Thank you for your suggestion. I will see if I can use something like this in my app and I will let you know whether it works for me. – ashleyjbartlett May 28 '20 at 14:36
  • cool. I use such caching in my app and it works pretty good cross browsers. In my case this also reduces the number of download requests on server and provides better offline first experience – Sergey Rudenko May 28 '20 at 14:48