DEV Community

Cover image for The download capability of Web components
liu yang
liu yang

Posted on

The download capability of Web components

Handling Page-Triggered Downloads in HarmonyOS Next

Overview

The Web component in HarmonyOS Next allows developers to manage downloads triggered by the frontend page. By registering a DownloadDelegate using the setDownloadDelegate() method, developers can monitor and manage the download process. The Web component handles the actual downloading of resources and notifies the application of download progress through the DownloadDelegate.

Example: Monitoring Download Progress

In the following example, an index.html and a download.html file are created in the application's rawfile directory. When the application starts, it creates a Web component and loads index.html. Clicking the setDownloadDelegate button registers a DownloadDelegate with the Web component. When the download button on the page is clicked, a download task is triggered, and the DownloadDelegate listens for download progress updates.

Application-Side Code

// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  delegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate();

  build() {
    Column() {
      Button('Set Download Delegate')
        .onClick(() => {
          try {
            this.delegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
              console.log("Download is about to start.");
              // Specify a download path and start the download.
              // If an invalid path is provided, the file will be downloaded to the default /data/storage/el2/base/cache/web/ directory.
              webDownloadItem.start("/data/storage/el2/base/cache/web/" + webDownloadItem.getSuggestedFileName());
            });
            this.delegate.onDownloadUpdated((webDownloadItem: webview.WebDownloadItem) => {
              // Unique identifier for the download task.
              console.log("Download update GUID: " + webDownloadItem.getGuid());
              // Download progress.
              console.log("Download progress: " + webDownloadItem.getPercentComplete());
              // Current download speed.
              console.log("Download speed: " + webDownloadItem.getCurrentSpeed());
            });
            this.delegate.onDownloadFailed((webDownloadItem: webview.WebDownloadItem) => {
              console.log("Download failed GUID: " + webDownloadItem.getGuid());
              // Error code for the failed download task.
              console.log("Error code: " + webDownloadItem.getLastErrorCode());
            });
            this.delegate.onDownloadFinish((webDownloadItem: webview.WebDownloadItem) => {
              console.log("Download finished GUID: " + webDownloadItem.getGuid());
            });
            this.controller.setDownloadDelegate(this.delegate);
          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
          }
        });
      Web({ src: $rawfile('index.html'), controller: this.controller });
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Frontend Page Code (index.html)

<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
    <!-- Clicking the download button in the video's bottom-right menu triggers a download task. -->
    <video controls="controls" width="800px" height="580px"
           src="http://vjs.zencdn.net/v/oceans.mp4"
           type="video/mp4">
    </video>
    <a href='data:text/html,%3Ch1%3EHello%2C%20World%21%3C%2Fh1%3E' download='download.html'>Download download.html</a>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Downloadable HTML File (download.html)

<!-- download.html -->
<!DOCTYPE html>
<html>
<body>
    <h1>Download Test</h1>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Initiating a Download Task with the Web Component

The startDownload() interface can be used to initiate a download task. The Web component calculates the referrer based on the current URL and the default Referrer Policy of the Web component.

In the following example, clicking the setDownloadDelegate button registers a listener with the Web component, and then clicking startDownload initiates a download task. The download progress is notified to the application through the set DownloadDelegate.

Application-Side Code

// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  delegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate();

  build() {
    Column() {
      Button('Set Download Delegate')
        .onClick(() => {
          try {
            this.delegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
              console.log("Download is about to start.");
              // Specify a download path and start the download.
              webDownloadItem.start("/data/storage/el2/base/cache/web/" + webDownloadItem.getSuggestedFileName());
            });
            this.delegate.onDownloadUpdated((webDownloadItem: webview.WebDownloadItem) => {
              console.log("Download update GUID: " + webDownloadItem.getGuid());
            });
            this.delegate.onDownloadFailed((webDownloadItem: webview.WebDownloadItem) => {
              console.log("Download failed GUID: " + webDownloadItem.getGuid());
            });
            this.delegate.onDownloadFinish((webDownloadItem: webview.WebDownloadItem) => {
              console.log("Download finished GUID: " + webDownloadItem.getGuid());
            });
            this.controller.setDownloadDelegate(this.delegate);
          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
          }
        });
      Button('Start Download')
        .onClick(() => {
          try {
            // Specify the download URL as "https://www.example.com/", and the Web component will initiate a download task to download the page.
            // Developers should replace this with the actual URL of the content they wish to download.
            this.controller.startDownload("https://www.example.com/");
          } catch (error) {
            console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
          }
        });
      Web({ src: 'https://www.example.com/', controller: this.controller });
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)