HarmonyOS之深入解析如何根据url下载pdf文件并且在本地显示和预览

一、文件下载

① 网络请求配置
  • 下载在线文件,需要访问网络,因此需要在 config.json 中添加网络权限:
{"module": {"requestPermissions": [{"name": "ohos.permission.INTERNET","reason": "下载文件需要网络访问"},{"name": "ohos.permission.READ_MEDIA","reason": "访问下载文件"},{"name": "ohos.permission.WRITE_MEDIA","reason": "保存下载文件"}]}
}
② 文件下载核心代码
import http from '@ohos.net.http';let httpRequest = http.createHttp()let opt: http.HttpRequestOptions = {method: http.RequestMethod.GET,header: { 'Accept-Encoding': 'gzip, deflate, br','Accept-Language': 'zh-CN,zh;q=0.9','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',},expectDataType: http.HttpDataType.ARRAY_BUFFER}httpRequest.request(url, opt).then((resp) => {let respDisp: string = resp.header["content-disposition"]// 从文件信息提取文件名称,包含双引号let fileNameWithQuote = respDisp.split(";")[1].split("=")[1]// 去掉文件名称的双引号let fileName = fileNameWithQuote.substring(1, fileNameWithQuote.length - 1)// 保存文件到本地let filePath = this.saveFile(resp.result as ArrayBuffer, fileName)if (filePath.length > 0) {let msgHistory = "文件已保存到:" + filePath + "\r\n"toast('下载成功,可在“我的下载”中查看下载的附件')} else {toast('保存失败')}}).catch((e:Error) => {toast('下载失败')})
③ 保存文件到本地
import fs from '@ohos.file.fs'// 保存文件并返回保存路径saveFile(buf: ArrayBuffer, fileName: string): string {let pathDir = getContext(this).filesDirlet filePath = pathDir + "/" + fileNamelet file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)fs.writeSync(file.fd, buf)fs.closeSync(file)return filePath}

二、文件的读取

  • 在上面的文件被下载后,我们已经将文件保存到我们的本地路径中,那么该如何读取这些文件呢?
import fs from '@ohos.file.fs'@State filesArray : MyDownloadDataModel[] = []getListFile(): void {// 获取当前应用的文件目录路径let pathDir = getContext(this).filesDir// 配置文件列表的筛选选项let listFileOption: ListFileOptions = {recursion: false,  // 不递归子目录listNum: 0,		  // 0表示获取所有符合条件的文件filter: {suffix: [".pdf"], // 只筛选这些后缀的文件fileSizeOver: 0             // 文件大小超过0字节(即所有大小)}};// 同步获取目录下符合条件的文件列表let files = fs.listFileSync(pathDir, listFileOption);// 遍历所有匹配的文件for (let i = 0; i < files.length; i++) {// 拼接文件的完整路径let filePath = pathDir + '/' + files[i]// 创建文件数据模型对象let model = new MyDownloadDataModelmodel.fileName = files[i]model.filePath = filePathmodel.fileType = files[i].split('.')[1]// 异步获取文件大小信息fs.stat(filePath).then((stat: fs.Stat) => {// 计算文件大小(转换为MB)let size = stat.size / 1024 / 1024// 设置文件大小字符串表示(示例中实际用的是KB单位)model.fileSize = stat.size.toString() + "KB"}).catch((err: BusinessError) => {// 如果获取大小失败,设置默认值0model.fileSize = "0 KB"});// 异步获取文件创建时间信息fs.lstat(filePath).then((stat: fs.Stat) => {// 将时间戳转换为可读格式model.fileCreateTime = DateRsUtil.getDateStringWithTimeStamp(stat.ctime)// 将完整模型对象加入数组this.filesArray.push(model)}).catch((err: BusinessError) => {model.fileCreateTime = ''this.filesArray.push(model)});}
}

三、预览文件

① 使用系统预览能力(推荐)
// 获取当前UI上下文对象(用于界面相关操作)
let uiContext = getContext(this);// 配置预览窗口的显示参数
let displayInfo: filePreview.DisplayInfo = {x: 100,      // 预览窗口左上角的x坐标(单位:像素)y: 100,      // 预览窗口左上角的y坐标(单位:像素)width: 800,  // 预览窗口的宽度(单位:像素)height: 800  // 预览窗口的高度(单位:像素)
};// 配置要预览的文件信息
let fileInfo: filePreview.PreviewInfo = {title: file.fileName,  // 设置预览窗口标题为文件名uri: fileUri.getUriFromPath(file.filePath),  // 将文件路径转换为URI格式mimeType: 'application/pdf'  // 明确指定文件类型为PDF
};// 调用文件预览功能
filePreview.openPreview(uiContext, fileInfo, displayInfo).then(() => {// 预览成功回调console.info('Succeeded in opening preview');}).catch((err: BusinessError) => {// 预览失败回调console.error(`Failed to open preview, err.code = ${err.code},  // 错误码err.message = ${err.message}`  // 错误描述);});
② Web组件预览(备选)
import webview from '@ohos.web.webview';@Component
struct PdfWebView {controller: webview.WebviewController = new webview.WebviewController();build() {Column() {Web({src: $rawfile('downloaded.pdf'), // 或使用file://路径controller: this.controller}).onPageEnd(e => {console.info('PDF加载完成');})}}
}

四、分享文件

requestShareFile(file: MyDownloadDataModel) {// 构造ShareData,需配置一条有效数据信息let data: systemShare.SharedData = new systemShare.SharedData({utd: utd.UniformDataType.PDF,content: file.fileName});let uiContext = getContext(this)// 获取文件的沙箱路径let pathInSandbox = uiContext.filesDir + file.filePath// 将沙箱路径转换为urilet uri = fileUri.getUriFromPath(pathInSandbox)// 添加多条记录data.addRecord({utd: utd.UniformDataType.PDF,uri: uri});// 构建ShareControllerlet controller: systemShare.ShareController = new systemShare.ShareController(data)// 注册分享面板关闭监听controller.on('dismiss', () => {// 分享结束,可处理其他业务});// 进行分享面板显示let context = getContext(this) as common.UIAbilityContext;controller.show(context, {previewMode: systemShare.SharePreviewMode.DETAIL,selectionMode: systemShare.SelectionMode.SINGLE});}

五、高级功能扩展

① 断点续传
const downloadRange = (url: string, filePath: string, start: number) => {const file = fileio.openSync(filePath, fileio.O_RDWR);fileio.lseekSync(file.fd, start, fileio.SeekType.SEEK_SET);return http.request(url, {header: { 'Range': `bytes=${start}-` },file: file.fd});
};
② 文件缓存管理
function cleanOldPdfs(maxAge: number = 7 * 24 * 3600 * 1000) {const dir = fileio.opendirSync('internal://cache/');const now = Date.now();for (const entry of dir.readSync()) {if (entry.name.endsWith('.pdf')) {const stat = fileio.statSync(`internal://cache/${entry.name}`);if (now - stat.mtime * 1000 > maxAge) {fileio.unlinkSync(`internal://cache/${entry.name}`);}}}
}

六、注意事项

① 安全性
  • 验证下载URL的合法性;
  • 检查文件签名(如有);
  • 敏感文件建议加密存储。
② 性能优化
  • 大文件分块下载(如 10MB/块);
  • 预览前校验文件头是否为%PDF;
③ 兼容性处理
function tryOpenWithWebView(filePath: string) {try {// 尝试转换为content:// URIconst uri = fileuri.getUriFromPath(filePath, 'content');// 调用系统文件选择器// ...} catch (error) {prompt.showToast({ message: '无法打开PDF文件' });}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙前后端项目源码-点餐v3.0-原创!原创!原创!

鸿蒙前后端点餐项目源码含文档ArkTS语言. 原创作品.我半个月写的原创作品&#xff0c;请尊重原创。 原创作品&#xff0c;盗版必究&#xff01;&#xff01;&#xff01;&#xff01; 原创作品&#xff0c;盗版必究&#xff01;&#xff01;&#xff01;&#xff01; 原创作…

VUE3+TypeScript项目,使用html2Canvas+jspdf生成PDF并实现--分页--页眉--页尾

使用html2CanvasJsPDF生成pdf&#xff0c;并实现分页添加页眉页尾 1.封装方法htmlToPdfPage.ts /**path: src/utils/htmlToPdfPage.tsname: 导出页面为PDF格式 并添加页眉页尾 **/ /*** 封装思路* 1.将页面根据A4大小分隔边距&#xff0c;避免内容被中间截断* 所有元素层级不要…

5.Excel:从网上获取数据

一 用 Excel 数据选项卡获取数据的方法 连接。 二 要求获取实时数据 每1分钟自动更新数据。 A股市场_同花顺行情中心_同花顺财经网 用上面方法将数据加载进工作表中。 在表格内任意区域右键&#xff0c;刷新。 自动刷新&#xff1a; 三 缺点 Excel 只能爬取网页上表格类型的…

《深度剖析SQL之WHERE子句:数据过滤的艺术》

在当今数据驱动的时代&#xff0c;数据处理和分析能力已成为职场中至关重要的技能。SQL作为一种强大的结构化查询语言&#xff0c;在数据管理和分析领域占据着核心地位。而WHERE子句&#xff0c;作为SQL中用于数据过滤的关键组件&#xff0c;就像是一把精准的手术刀&#xff0c…

华为eNSP-配置静态路由与静态路由备份

一、静态路由介绍 静态路由是指用户或网络管理员手工配置的路由信息。当网络拓扑结构或者链路状态发生改变时&#xff0c;需要网络管理人员手工修改静态路由信息。相比于动态路由协议&#xff0c;静态路由无需频繁地交换各自的路由表&#xff0c;配置简单&#xff0c;比较适合…

Docker 快速入门指南

Docker 快速入门指南 1. Docker 常用指令 Docker 是一个轻量级的容器化平台&#xff0c;可以帮助开发者快速构建、测试和部署应用程序。以下是一些常用的 Docker 命令。 1.1 镜像管理 # 搜索镜像 docker search <image_name># 拉取镜像 docker pull <image_name>…

基础认证-单选题(一)

单选题 1、下列关于request方法和requestlnStream方法说法错误的是(C) A 都支持取消订阅响应事件 B 都支持订阅HTTP响应头事件 C 都支持HttpResponse返回值类型 D 都支持传入URL地址和相关配置项 2、如需修改Text组件文本的透明度可通过以下哪个属性方法进行修改 (C) A dec…

Logback使用和常用配置

Logback 是 Spring Boot 默认集成的日志框架&#xff0c;相比 Log4j&#xff0c;它性能更高、配置更灵活&#xff0c;并且天然支持 Spring Profile 多环境配置。以下是详细配置步骤及常用配置示例。 一、添加依赖&#xff08;非 Spring Boot 项目&#xff09; 若项目未使用 Sp…

MySQL基础语法DDLDML

目录 #1.创建和删除数据库 ​#2.如果有lyt就删除,没有则创建一个新的lyt #3.切换到lyt数据库下 #4.创建数据表并设置列及其属性,name是关键词要用name包围 ​编辑 #5.删除数据表 #5.查看创建的student表 #6.向student表中添加数据,数据要与列名一一对应 #7.查询studen…

在windows下安装windows+Ubuntu16.04双系统(下)

这篇文章的内容主要来源于这篇文章&#xff0c;为正式安装windowsUbuntu16.04双系统部分。在正式安装前&#xff0c;若还没有进行前期准备工作&#xff08;1.分区2.制作启动u盘&#xff09;&#xff0c;见《在windows下安装windowsUbuntu16.04双系统(上)》 二、正式安装Ubuntu …

Ubuntu24.04 离线安装 MySQL8.0.41

一、环境准备 1.1 官方下载MySQL8.0.41 完整包 1.2 上传包 & 解压 上传包名称是&#xff1a;mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundle.tar # 切换到上传目录 cd /home/MySQL8 # 解压&#xff1a; tar -xvf mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundl…

记录一次Dell服务器更换内存条报错解决过程No memory found

文章目录 问题问题分析解决流程总结 问题 今天给服务器添加了几个内存条&#xff0c;开启后报错 No memory found No useable DlMMs found. Verify the DlMMsare properly seated and that they are installed in the correct sockets. 问题分析 这个错误说明服务器在启动时没…

Apache HttpClient使用

一、Apache HttpClient 基础版 HttpClients 是 Apache HttpClient 库中的一个工具类&#xff0c;用于创建和管理 HTTP 客户端实例。Apache HttpClient 是一个强大的 Java HTTP 客户端库&#xff0c;用于发送 HTTP 请求并处理 HTTP 响应。HttpClients 提供了多种方法来创建和配…

Maven版本统一管理

多模块的项目&#xff0c;怎么方便管理 模块的版本号呢&#xff1f; 可以使用 ${revision} 配合 flatten-maven-plugin插件 <plugin><groupId>org.codehaus.mojo</groupId><artifactId>flatten-maven-plugin</artifactId><version>1.1.0&…

时序数据库 InfluxDB(一)

时序数据库 InfluxDB&#xff08;一&#xff09; 数据库种类有很多&#xff0c;比如传统的关系型数据库 RDBMS&#xff08; 如 MySQL &#xff09;&#xff0c;NoSQL 数据库&#xff08; 如 MongoDB &#xff09;&#xff0c;Key-Value 类型&#xff08; 如 redis &#xff09…

E5071C数据保存教程:SNP文件/CSV导出+远程传输步骤一键收藏

Keysight E5071C 网络分析仪支持多种数据存储方式&#xff0c;以下是详细的操作步骤和注意事项&#xff1a; 1. 内部存储&#xff08;仪器内存&#xff09; 保存测量数据&#xff1a; 轨迹数据&#xff1a;按 Save/Recall → Save Trace Data → 选择存储格式&#xff08;如 …

业务相关

目录 一、Spark 1.spark主要用来计算什么&#xff1f; 随便说段代码 2.spark 运行命令说一个&#xff0c;平常用哪些参数&#xff0c;怎么考虑的 3.spark shuffle的代码有哪些&#xff0c;平日哪些操作涉及到shuffle了 4.计算中遇到最难解决的是什么&#xff1f; 5.Spark …

LLM之RAG实战(五十二)| 如何使用混合搜索优化RAG 检索

在RAG项目中&#xff0c;大模型生成的参考内容&#xff08;专业术语称为块&#xff09;来自前一步的检索&#xff0c;检索的内容在很大程度上直接决定了生成的效果&#xff0c;因此检索对于RAG项目至关重要&#xff0c;最常用的检索方法是关键字搜索和语义搜索。本文将分别介绍…

[学成在线]07-视频转码

视频转码 视频上传成功后需要对视频进行转码处理。 首先我们要分清文件格式和编码格式&#xff1a; 文件格式&#xff1a;是指.mp4、.avi、.rmvb等这些不同扩展名的视频文件的文件格式 &#xff0c;视频文件的内容主要包括视频和音频&#xff0c;其文件格式是按照一定的编码…

Leetcode算法方法总结

1. 双指针法解决链表/数组题目 只要数组有序&#xff0c;就要想到双指针做法。还有二分法 回文串一般也会用到双指针&#xff0c;回文串的长度由于可能是奇数也可能是偶数&#xff0c;所以在寻找时&#xff0c;既需要寻找奇数长度的回文串&#xff0c;也需要寻找偶数长度的回文…