鸿蒙上实现文件上传功能
2023-05-22 14:21:52 OST开源开发者

此帖主要讲解通过开发文档示例代码写一个完整 Demo,方便初学者理解开发文档内容。

大家都知道 3.0 使用的是 FA 模式、3.1 使用的是 Stage 模式,所以同样是文件上传,代码写法上有些不一样,开发文档也不一样。


(相关资料图)

比如在 3.1 下,可以在 HarmonyOSDeveloper > 文档 > 指南 > 开发下找到文件上传下载示例代码。

而在 3.0 下,就找不到相应指南开发了,只能在 HarmonyOS Developer > 文档 > API参考 > ArkTS API 参考找到 @ohos.request (上传下载)文档。

为了实现一个完整文件上传 Demo,后端是少不了的,这里我使用了我平常工作中用到的 SpringBoot 开发后端。

为了验证文件上传接口是否正常,使用 Thymeleaf 写一个简单的前端页面来测试接口,先保证后端文件上传接口是正常的。

这样其它前端调用就可以排除后端文件上传接口问题,专心调试前端代码,希望小伙伴通过此贴学习到文件上传同时,参考此思路也可以自己完成其它示例代码完成 Demo。

效果如下:

ArkTS(3.0)文件管理(前端)

此版本使用的是 FA 模式、配置文件名是 config.json 由于文件上传需要网络,需要添加权限:ohos.permission.INTERNET,默认支持 https。

如果要支持 http,需要在 config.json 里增加 network 标签,属性标识 “cleartextTraffic”: true。

所以 config.json 要添加的内容以下:

{"app":{...},"deviceConfig":{"default":{"network":{"cleartextTraffic":true}}},"module":{"reqPermissions":[{"name":"ohos.permission.INTERNET"}]}}
文件上传页面就一个 index.ets 文件,里面包含 UI 和调用后端接口,代码如下:
importrequestfrom"@ohos.request";importfeatureAbilityfrom"@ohos.ability.featureAbility";importfileiofrom"@ohos.fileio";@Entry@ComponentstructIndex{@StatebtnLabel:string="提交文件"privateuploadTask:request.UploadTaskaboutToAppear(){//获取应用文件路径varcontext=featureAbility.getContext();context.getCacheDir().then((data)=>{console.info("xx======================>getCacheDirPromsie====================>");console.info("xx====>data====>"+JSON.stringify(data));//新建一个本地应用文件letfd=fileio.openSync(data+"/test.txt",0o102,0o666);fileio.writeSync(fd,"uploadfiletestbyarmy");fileio.closeSync(fd);});}aboutToDisappear(){this.uploadTask.off("progress")}uploadFile(){//上传任务配置项letuploadConfig={url:"http://111.114.238.134:8740/file/upload",header:{key1:"Content-Type",key2:"multipart/form-data"},method:"POST",files:[{filename:"test.txt",name:"test",uri:"internal://cache/test.txt",type:"txt"}],data:[{name:"fileId",value:"FP000008"}]}//将本地应用文件上传至网络服务器try{this.btnLabel="文件上传中..."request.upload(uploadConfig).then((data)=>{this.btnLabel="文件上传成功"this.uploadTask=dataconsole.info("xxSuccesstorequesttheupload.Cause:"+JSON.stringify(data));//uploadTask=data;this.uploadTask.on("progress",(uploadedSize,totalSize)=>{console.info("xx上传进度值是:"+uploadedSize+",总大小:"+totalSize)})}).catch((err)=>{this.btnLabel="文件上传失败"console.error("xxFailedtorequesttheupload.Cause:"+JSON.stringify(err));})}catch(err){this.btnLabel="文件上传失败"console.error(`xxInvokeuploadFilefailed,codeis${err.code},messageis${err.message}`);}}build(){Column({space:30}){Text("上传文件实例:").width("100%").height(50).fontSize(24).textAlign(TextAlign.Center)Button("提交文件").onClick(()=>{this.uploadFile()}).width("80%").height(50).fontSize(24)}.width("100%").height("100%").justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}

ArkTS(3.1)文件管理(前端)

此版本使用的是 Stage 模式、配置文件名是 module.json5 由于文件上传需要网络,需要添加权限:ohos.permission.INTERNET。

在 3.1 不用配置,就支持 http 和 https,当前上传应用文件功能,仅支持上传应用缓存文件路径(cacheDir)下的文件。

所以 module.json5 要添加的内容以下:

{"module":{"requestPermissions":[{"name":"ohos.permission.INTERNET"}]}}
文件上传页面就一个 index.ets 文件,里面包含 UI 和调用后端接口,代码如下:
importcommonfrom"@ohos.app.ability.common";importfsfrom"@ohos.file.fs";importrequestfrom"@ohos.request";importhashfrom"@ohos.file.hash";//获取应用文件路径letcontext=getContext(this)ascommon.UIAbilityContext;@Entry@ComponentstructIndex{@StatebtnLabel:string="提交文件"privateuploadTask:request.UploadTaskaboutToAppear(){letcacheDir=context.cacheDir;//新建一个本地应用文件letfile=fs.openSync(cacheDir+"/test.txt",fs.OpenMode.READ_WRITE|fs.OpenMode.CREATE);fs.writeSync(file.fd,"uploadfiletestbyAPI9");fs.closeSync(file);}aboutToDisappear(){this.uploadTask.off("complete")}uploadFile(){//上传任务配置项letuploadConfig={url:"http://111.114.238.134:8740/file/upload",header:{key1:"Content-Type",key2:"multipart/form-data"},method:"POST",files:[{filename:"test.txt",name:"test",uri:"internal://cache/test.txt",type:"txt"}],data:[{name:"fileId",value:"FP000008"}]}//将本地应用文件上传至网络服务器try{this.btnLabel="文件上传中..."request.uploadFile(context,uploadConfig).then((data)=>{this.btnLabel="文件上传成功"this.uploadTask=datathis.uploadTask.on("complete",(taskStates)=>{for(leti=0;i{this.btnLabel="文件上传失败"console.error(`xxInvokeuploadFilefailed,codeis${err.code},messageis${err.message}`);})}catch(err){this.btnLabel="文件上传失败"console.error(`xxInvokeuploadFilefailed,codeis${err.code},messageis${err.message}`);}}build(){Column({space:30}){Text("上传文件实例:").width("100%").height(50).fontSize(24).textAlign(TextAlign.Center)Button(this.btnLabel).onClick(()=>{this.uploadFile()}).width("80%").height(50).fontSize(24)}.width("100%").height("100%").justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}

SpringBoot 和 Thymeleaf(后端)

后端首先列出 pom.xml 文件,里面包含项目依赖jar配置,比如 web、thymeleaf 依赖。

内容如下:

4.0.0org.springframework.bootspring-boot-starter-parent2.3.1.RELEASE com.armyfile-manage0.0.1-SNAPSHOTfile-manageDemoprojectforSpringBoot8org.springframework.bootspring-boot-starter-thymeleaforg.springframework.bootspring-boot-starter-weborg.projectlomboklomboktrueorg.springframework.bootspring-boot-starter-testtestcommons-iocommons-io2.6org.springframework.bootspring-boot-maven-pluginorg.projectlomboklombok
前端调用接口文件 Controller 代码如下:
@RestController@RequestMapping("/file")@Slf4jpublicclassFileController{@AutowiredFileServicefileService;@PostMapping("/upload")publicStandardResponseupload(StringfileId,MultipartHttpServletRequestmultiPartRequest){log.info("**UploadFileController!");FileCriteriacriteria=newFileCriteria();criteria.setFileId(fileId);try{//uploadfileIteratoritr=multiPartRequest.getFileNames();MultipartFilempf=null;while(itr.hasNext()){mpf=multiPartRequest.getFile(itr.next());break;}byte[]fileByteArr=null;if(null!=mpf&&!mpf.isEmpty()){StringoriginalFileName=mpf.getOriginalFilename();log.info(originalFileName);criteria.setFileName("");StringfileExtension=FilenameUtils.getExtension(originalFileName);criteria.setFileExtension(fileExtension);fileByteArr=mpf.getBytes();criteria.setFileByteArray(fileByteArr);criteria.setFileName(originalFileName);}}catch(IOExceptione){e.printStackTrace();log.error(e.getMessage());}returnfileService.uploadFile(criteria);}}

后端业务逻辑代码,也就是文件上传处理逻辑 Service 代码如下:

业务接口:

publicinterfaceFileService{StandardResponseuploadFile(FileCriteriacriteria);StringsaveFile(FileCriteriacriteria);}
业务实现类:
@Service@Slf4jpublicclassFileServiceImplimplementsFileService{@Value("${project.root.path}")privateStringrootPath="rootPath";@Value("${project.baseUrl}")privateStringbaseUrl;@OverridepublicStandardResponseuploadFile(FileCriteriacriteria){StringfilePath=this.saveFile(criteria);StringimgPath=baseUrl+"filePath/"+filePath;StandardResponsestandardResponse=newStandardResponse();standardResponse.setSuccess(true);standardResponse.setStatusCode("100");standardResponse.setStatusDesc("上传成功");standardResponse.setData(imgPath);returnstandardResponse;}@OverridepublicStringsaveFile(FileCriteriacriteria){log.info("上传文件开始!");StringpictureId=IdUtils.getId("FP");StringfileName=pictureId+"."+criteria.getFileExtension();criteria.setFileName(fileName);StringfilePath=sourceFile(criteria);log.info("FilePath:"+filePath);log.info("上传文件结束!");returnfilePath;}privateStringsourceFile(FileCriteriacriteria){byte[]attachmentFileByteArray=criteria.getFileByteArray();if(null!=attachmentFileByteArray){log.info("1.1.创建根目录.");StringbasePath=rootPath+this.genDatePath();FilebasePathFolder=newFile(basePath);if(!basePathFolder.exists())basePathFolder.mkdirs();log.info("根目录:"+basePath);Filefile=newFile(basePath+File.separator+criteria.getFileName());log.info("1.2.保存源文件-绝对路径:"+file.getAbsolutePath());try{FileCopyUtils.copy(attachmentFileByteArray,file);log.info("1.3.1.保存源文件-保存成功!!!");StringrelativePath=this.genDatePath()+File.separator+criteria.getFileName();returnrelativePath;}catch(IOExceptione){log.info("1.3.2.保存源文件-保存失败!!!");file.deleteOnExit();return"";}}return"";}privateStringgenDatePath(){SimpleDateFormatsdf=newSimpleDateFormat("yyyyMMdd");StringyyyyMMdd=sdf.format(newDate());returnyyyyMMdd;}}
配置文件:
server:port:8740project:root:path:/var/tomcat/file-manage/filePath/baseUrl:http://111.114.238.134:8740/
访问域名或 IP 加端口访问到 Thymeleaf 页面,要添加一个 Controller 跳转。
@ControllerpublicclassIndexController{@GetMapping("/")publicStringIndex(){return"index";}}

在 templates 目录下创建 index.htm 页面文件,这里的 index 名要和上面 Controller 返回“index”名一致,才能跳转过去。

index.html 代码如下:

单文件上传

上面图片就是 Thymeleaf 页面,上传文件成功后效果。

总结

通过此贴学习到文件上传 3.0 与 3.1 的不同处,同时也学习到了后端开发流程。 其实写这个贴子之前,是一个小伙伴问到我关于文件上传问题,由于之前我写的实例里,也没有用到文件上传功能,于是我就用最新API9 也就是 Stage 模式写了一个 Demo 给他参考,然后他通过参考我的 Demo,学会了。 可惜他现在开发的项目是用 API8 的,由于开发模式不一样,他遇到了问题,于是我在用 API8 写了一个 Demo 给他参考,最后他的项目也实现了文件上传。

审核编辑:汤梓红

热门推荐

文章排行

  1. 2023-05-22鸿蒙上实现文件上传功能
  2. 2023-05-22天天观察:ST迪威迅股东户数下降2.40%,户均持股5.84万元
  3. 2023-05-22环球速看:微信信息同步到电脑为什么没有同步?_微信消息同步到电脑
  4. 2023-05-225月22日山东东银金属材料无缝管价格下跌 观天下
  5. 2023-05-22安逸花逾期怎么样协商?安逸花逾期还不上会怎样?-今热点
  6. 2023-05-22倚锋资本朱晋桥:投资创业者需要等风口来、顺势而为 快讯
  7. 2023-05-22胡蝶兰开完花后如何养在开花(胡蝶兰开完花后如何养在开花前浇水)
  8. 2023-05-22观热点:朱民:2050年中国碳中和累计投资规模预计约180万亿元
  9. 2023-05-22天天微速讯:“互换通”有望吸引外资 深度参与中国债市
  10. 2023-05-21外媒:《赛博朋克2077》续作可以讨论时间旅行 今日要闻
  11. 2023-05-22400年前的画里有男孩穿耐克鞋?
  12. 2023-05-21车联网提升/驾乘更舒适便捷 试驾全新捷达VS7高光版 天天实时
  13. 2023-05-21好样的!陈雨菲2比0胜安冼莹,证明自己,助国羽夺得苏迪曼杯
  14. 2023-05-21天天报道:套内面积和建筑面积的区别_套内面积算墙体吗
  15. 2023-05-21当前信息:Alin参加节目帮女儿追星马嘉祺 两人的梦幻联动
  16. 2023-05-21兴农有“荔”量,乡村添能量|天天讯息
  17. 2023-05-21快资讯丨莱巴收退赛礼夺冠,双鲁会鲁内逆转,梅西决梅总赢球,张帅复出
  18. 2023-05-21天天观点:上班工作时间简介介绍给领导_上班工作时间简介介绍
  19. 2023-05-21湖北襄阳签约7GWh储电项目 全球最资讯
  20. 2023-05-21天天热讯:太阳报报道瓜帅妻子:巴西记者兼作家,两人18岁相识育有3子