本文主要记录使用两种下载文件的方法踩到的坑(基于api 16)及对应的处理方式, 至于具体用法请自行参考官方文档
背景: 关于文件下载, 目前使用到的方法有以下两种:
- ohos.request ## downloadFile : 文件太小时有遇到问题
- rcp.createSession ## downloadToFile : 文件太大时有遇到问题
问题1: 使用reuest.downloadFile下载小文件(如几KB甚至更小的缩略图)时, 下载完成后并不会触发 下载完成(onComplete)的回调, 需要根据下载进度(progress)判断是否下载完成
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
try {
request.downloadFile(context, { url: 'https://xxxx/xxxx.hap' }).then((data: request.DownloadTask) => {
// 1. 当文件很小时, 下载完成后不会执行这个回调
let downloadTask: request.DownloadTask = data;
let completeCallback = () => {
console.info('Download task completed.');
};
downloadTask.on('complete', completeCallback);
// 2. 需要在下载进度的回调中判断是否下载完成、 并执行下载完成的逻辑
let progressCallback = (receivedSize: number, totalSize: number) => {
if ( receivedSize === totalSize ) {
// .... 下载完成的逻辑
}
};
downloadTask.on('progress', progressCallback);
}).catch((err: BusinessError) => {
console.error(`Failed to request the download. Code: ${err.code}, message: ${err.message}`);
})
} catch (err) {
console.error(`Failed to request the download. err: ${JSON.stringify(err)}`);
}
问题2: 使用rcp.session进行切片下载时, 如果单个分片大小超过50MB, 能下载成功、但会写入文件失败, 需要严格确保切片不超过50MB
/**
* 下载文件指定位置的文件切片
*
* @param index 第n个切片
* @param start 当前切片第一个字节在文件中的位置下标
* @param end 当前切片最后一个字节在文件中的位置下标
*
* 当end-start > 50*1024*1024时, 即指定的分片大于50MB, 能下载成功但会写文件失败
*/
private downloadPart(index: number start: number, end: number ) {
const sessionConfig: rcp.SessionConfiguration = ...
const session = rcp.createSession(sessionConfig);
const req = new rcp.Request(this.url, "GET", {
'Range': `bytes=${start}-${end}`
});
// 分块内容
session.fetch(req).then(( response: rcp.Response ) => {
// 处理下载结果
if ( response.statusCode === 206 && response.body ) {
// 将数据保存到临时文件
const path = `${this.context.tempDir}/downloaded_file_part_${index}.part`
const file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
/*******************************************************/
// 超过50MB时会导致写入失败 {"code":1007900023,"data":"Failed writing received data to disk/application","extendInfo":xxx}
// 解决方案: 现通过 downloadAssistant 对分块大小进行控制、计算
fs.write(file.fd, response.body).then(( value: number ) => {
//console.info(TAG + "成功 ===>>>> Downloaded and write success:", index, value);
/*******************************************************/
})
}
session.close()
}).catch(( error: BusinessError ) => {
// 异常处理...
});
}