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 });
}
}
}
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>
Downloadable HTML File (download.html
)
<!-- download.html -->
<!DOCTYPE html>
<html>
<body>
<h1>Download Test</h1>
</body>
</html>
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 });
}
}
}
Top comments (0)