qidao123.com技术社区-IT企服评测·应用市场

标题: 鸿蒙开发系列(HarmonyOS)通过Request部件下载文件到本地场景实践 [打印本页]

作者: 天空闲话    时间: 4 天前
标题: 鸿蒙开发系列(HarmonyOS)通过Request部件下载文件到本地场景实践
鸿蒙NEXT开发实战往期必看文章:
一分钟了解”纯血版!鸿蒙HarmonyOS Next应用开发!
“非常具体的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到醒目)
HarmonyOS NEXT应用开发案例实践总结合(一连更新......)
HarmonyOS NEXT应用开发性能优化实践总结(一连更新......)

1. Request下载文件简介

在前述文章使用HttpRequest下载文件到本地示例中,使用基础的HttpRequest模块演示了怎样下载文件到本地,整个下载过程看起来似乎不太复杂,但是,如果考虑到可靠性、网络题目以及文件范例和大小的差异,开发难度还是相当大的,幸运的是,鸿蒙提供了专门用来进行上传下载的API,把这些复杂性都封装了起来,这就是本示例要使用的request部件。
2. request的常用方法

鸿蒙封装的request对象位于模块request中,使用如下的方式导入:
   import request from '@ohos.request';
  request模块包罗了众多的对象和利用方法,就本文而言,重点需要掌握的是downloadFile方法:
downloadFile(context: BaseContext, config: DownloadConfig): Promise<DownloadTask>
该方法实行异步下载,使用promise形式返回结果,结果为DownloadTask范例。可以通过DownloadTask范例的on('complete'|'pause'|'remove')订阅任务下载时的状态信息,包罗任务完成、停息或移除。通过on('fail')可获取任务下载时的错误信息。
3. request下载示例

本文要下载的服务端网站和使用HttpRequest下载文件到本地示例中的网站一样,也是需要登录后才可以下载,本示例运行后的界面如图所示:


应用启动后起首配置用户名密码以及登录地点,然后单击“登录”按钮进行登录,乐成登录后就可以单击“下载”按钮进行下载了,乐成下载后会体现生存位置和下载的文件内容。
下面具体先容创建该应用的步骤。
步骤1:创建Empty Ability项目。
步骤2:在module.json5配置文件加上对权限的声明:
  1. "requestPermissions": [
  2.       {
  3.         "name": "ohos.permission.INTERNET"
  4.       }
  5.     ]
复制代码
这里添加了访问互联网的权限。
步骤3:在Index.ets文件里添加如下的代码:
  1. import http from '@ohos.net.http';
  2. import util from '@ohos.util';
  3. import fs from '@ohos.file.fs';
  4. import request from '@ohos.request';
  5. import picker from '@ohos.file.picker';
  6. @Entry
  7. @Component
  8. struct Index {
  9.   //连接、通讯历史记录
  10.   @State msgHistory: string = ''
  11.   //首页地址
  12.   @State downloadUrl: string = "http://192.168.100.101:8081/download?filename=demo.txt"
  13.   //登录地址
  14.   @State loginUrl: string = "http://192.168.100.101:8081/auth"
  15.   //用户名
  16.   @State loginName: string = "zhanglei"
  17.   //密码
  18.   @State passwd: string = "cangjie"
  19.   //下载到本地的路径
  20.   @State localFilePath: string = ""
  21.   scroller: Scroller = new Scroller()
  22.   sessionId: string = ""
  23.   build() {
  24.     Row() {
  25.       Column() {
  26.         Text("Request下载示例")
  27.           .fontSize(14)
  28.           .fontWeight(FontWeight.Bold)
  29.           .width('100%')
  30.           .textAlign(TextAlign.Center)
  31.           .padding(10)
  32.         Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
  33.           Text("用户名:")
  34.             .fontSize(14)
  35.             .width(80)
  36.             .flexGrow(0)
  37.           TextInput({ text: this.loginName })
  38.             .onChange((value) => {
  39.               this.loginName = value
  40.             })
  41.             .width(110)
  42.             .fontSize(11)
  43.             .flexGrow(1)
  44.           Text("密码:")
  45.             .fontSize(14)
  46.             .width(60)
  47.             .flexGrow(0)
  48.           TextInput({ text: this.passwd })
  49.             .onChange((value) => {
  50.               this.passwd = value
  51.             })
  52.             .type(InputType.Password)
  53.             .width(100)
  54.             .fontSize(11)
  55.             .flexGrow(1)
  56.         }
  57.         .width('100%')
  58.         .padding(10)
  59.         Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
  60.           Text("登录地址:")
  61.             .fontSize(14)
  62.             .width(80)
  63.             .flexGrow(0)
  64.           TextInput({ text: this.loginUrl })
  65.             .onChange((value) => {
  66.               this.loginUrl = value
  67.             })
  68.             .width(100)
  69.             .fontSize(11)
  70.             .flexGrow(1)
  71.           Button("登录")
  72.             .onClick(() => {
  73.               this.login()
  74.             })
  75.             .width(70)
  76.             .fontSize(14)
  77.             .flexGrow(0)
  78.         }
  79.         .width('100%')
  80.         .padding(10)
  81.         Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
  82.           Text("文件地址:")
  83.             .fontSize(14)
  84.             .width(80)
  85.             .flexGrow(0)
  86.           TextInput({ text: this.downloadUrl })
  87.             .onChange((value) => {
  88.               this.downloadUrl = value
  89.             })
  90.             .width(110)
  91.             .fontSize(11)
  92.             .flexGrow(1)
  93.           Button("下载")
  94.             .onClick(() => {
  95.               this.downloadFile()
  96.             })
  97.             .width(70)
  98.             .fontSize(14)
  99.             .flexGrow(0)
  100.         }
  101.         .width('100%')
  102.         .padding(10)
  103.         Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
  104.           Text("保存位置:")
  105.             .fontSize(14)
  106.             .width(80)
  107.             .flexGrow(0)
  108.           TextInput({ text: this.localFilePath })
  109.             .width(110)
  110.             .fontSize(11)
  111.             .flexGrow(1)
  112.         }
  113.         .width('100%')
  114.         .padding(10)
  115.         Scroll(this.scroller) {
  116.           Text(this.msgHistory)
  117.             .textAlign(TextAlign.Start)
  118.             .padding(10)
  119.             .width('100%')
  120.             .backgroundColor(0xeeeeee)
  121.         }
  122.         .align(Alignment.Top)
  123.         .backgroundColor(0xeeeeee)
  124.         .height(300)
  125.         .flexGrow(1)
  126.         .scrollable(ScrollDirection.Vertical)
  127.         .scrollBar(BarState.On)
  128.         .scrollBarWidth(20)
  129.       }
  130.       .width('100%')
  131.       .justifyContent(FlexAlign.Start)
  132.       .height('100%')
  133.     }
  134.     .height('100%')
  135.   }
  136.   //下载文件
  137.   downloadFile() {
  138.     this.localFilePath = getContext(this).tempDir + "/demo.txt"
  139.     //文件如果已经存在,就删除
  140.     if (fs.accessSync(this.localFilePath)) {
  141.       fs.unlink(this.localFilePath)
  142.     }
  143.     let cfg: request.DownloadConfig = {
  144.       url: this.downloadUrl,
  145.       header: {
  146.         'Accept-Encoding': 'gzip, deflate, br',
  147.         'Accept-Language': 'zh-CN,zh;q=0.9',
  148.         //这一步很关键,把登录成功后的cookie传递过去
  149.         'Cookie': 'sessionid=' + this.sessionId,
  150.         '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',
  151.       },
  152.       filePath: this.localFilePath }
  153.     let downloadTask: request.DownloadTask;
  154.     try {
  155.       request.downloadFile(getContext(this), cfg
  156.         , (err, data) => {
  157.           if (err) {
  158.             console.error('Failed to request the download. Cause: ' + JSON.stringify(err));
  159.             return;
  160.           }
  161.           downloadTask = data;
  162.           downloadTask.on("progress", (size, tot) => {
  163.             this.msgHistory += `下载进度:${size}/${tot}\r\n`
  164.           })
  165.           downloadTask.on("complete", () => {
  166.             this.msgHistory += "下载完成\r\n"
  167.             //读取文件内容并显示
  168.             this.showFileContent(this.localFilePath)
  169.           })
  170.         });
  171.     } catch (err) {
  172.       this.msgHistory += 'err.code : ' + err.code + ', err.message : ' + err.message;
  173.     }
  174.   }
  175.   //显示指定文件的内容
  176.   showFileContent(filePath: string) {
  177.     let content = fs.readTextSync(filePath)
  178.     this.msgHistory += "文件内容:" + content + "\r\n"
  179.   }
  180.   //模拟登录
  181.   login() {
  182.     //http请求对象
  183.     let httpRequest = http.createHttp();
  184.     //请求的登录名和密码参数
  185.     let params = "username=" + this.loginName + "&password=" + this.passwd
  186.     let opt: http.HttpRequestOptions = {
  187.       method: http.RequestMethod.POST,
  188.       extraData: params,
  189.       header: { 'Content-Type': 'application/x-www-form-urlencoded' },
  190.       expectDataType: http.HttpDataType.STRING
  191.     }
  192.     httpRequest.request(this.loginUrl, opt)
  193.       .then((resp) => {
  194.         this.msgHistory += "响应码:" + resp.responseCode + "\r\n"
  195.         //返回的首部信息中,cookie的格式为:
  196.         // set-cookie: sessionid=19837d50s270ms999us100ns; Max-Age=1800; Path=/
  197.         //这里需要记录下sessionid,作为下次提交时的cookie信息
  198.         let cookies: string = resp.header["set-cookie"]
  199.         this.sessionId = cookies.split(";")[0].split("=")[1]
  200.         this.msgHistory += "sessionId:" + this.sessionId + "\r\n"
  201.         this.msgHistory += "登录成功\r\n"
  202.       })
  203.       .catch((e) => {
  204.         this.msgHistory += "登录失败:" + e.message + "\r\n"
  205.       })
  206.   }
  207. }
复制代码
步骤4:编译运行,可以使用模拟器大概真机。
步骤5:配置网站首页地点和登录地点,然后单击“登录”按钮,就可以模拟登录了,登录后的页面如图所示:


步骤6:单击“下载”按钮,应用会下载文件并生存到本地,然后从本地读取文件的内容(假设文件是文本范例的),如图所示:


可以看到,文件乐成生存到了本地并读取到了文件的内容。
3. 下载功能分析

要实现下载功能,关键点和使用httpRequest一样,也是要获取sessionId,而且在发起下载任务的DownloadConfig配置里通过header附加上sessionid,代码如下:
  1. let cfg: request.DownloadConfig = {
  2.       url: this.downloadUrl,
  3.       header: {
  4.         'Accept-Encoding': 'gzip, deflate, br',
  5.         'Accept-Language': 'zh-CN,zh;q=0.9',
  6.         //这一步很关键,把登录成功后的cookie传递过去
  7.         'Cookie': 'sessionid=' + this.sessionId,
  8.         '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',
  9.       },
  10.       filePath: this.localFilePath }
复制代码
另外要注意的一点是,如果文件下载过一次,再次下载时会提示本地文件已经存在,如许就会下载失败,解决方法是在下载前判断文件是否存在,如果存在就先删除,代码如下:
  1.     this.localFilePath = getContext(this).tempDir + "/demo.txt"
  2.     //文件如果已经存在,就删除
  3.     if (fs.accessSync(this.localFilePath)) {
  4.       fs.unlink(this.localFilePath)
  5.     }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4