此帖主要讲解通过开发文档示例代码写一个完整Demo,方便初学者理解开发文档内容。
想了解更多关于开源的内容,请访问:
【资料图】
清一色开源基础软件社区
https://ost.51cto.com
此帖主要讲解通过开发文档示例代码写一个完整Demo,方便初学者理解开发文档内容,大家都知道3.0使用的是FA模式、3.1使用的是Stage模式,所以同样是文件上传,代码写法上有些不一样,开发文档也不一样,比如在3.1下,可以在HarmonyOS Developer > 文档 > 指南 > 开发下找到文件上传下载示例代码,而在3.0下,就找不到相应指南开发了,只能在HarmonyOS Developer > 文档 > API参考 > ArkTS API参考找到@ohos.request (上传下载)文档,为了实现一个完整文件上传Demo,后端是少不了的,这里我使用了我平常工作中用到的SpringBoot开发后端,为了验证文件上传接口是否正常,使用Thymeleaf写一个简单的前端页面来测试接口,先保证后端文件上传接口是正常的,这样其它前端调用就可以排除后端文件上传接口问题,专心调试前端代码,希望小伙伴通过此贴学习到文件上传同时,参考此思路也可以自己完成其它示例代码完成Demo。
{ "app": {...}, "deviceConfig": { "default": { "network": { "cleartextTraffic": true } } }, "module": { "reqPermissions": [ { "name": "ohos.permission.INTERNET" } ] }}
文件上传页面就一个index.ets文件,里面包含UI和调用后端接口,代码如下:import request from "@ohos.request";import featureAbility from "@ohos.ability.featureAbility";import fileio from "@ohos.fileio";@Entry@Componentstruct Index { @State btnLabel: string = "提交文件" private uploadTask: request.UploadTask aboutToAppear() { // 获取应用文件路径 var context = featureAbility.getContext(); context.getCacheDir().then((data) => { console.info("xx ======================>getCacheDirPromsie====================>"); console.info("xx ====>data====>" + JSON.stringify(data)); // 新建一个本地应用文件 let fd = fileio.openSync(data + "/test.txt", 0o102, 0o666); fileio.writeSync(fd, "upload file test by army"); fileio.closeSync(fd); }); } aboutToDisappear() { this.uploadTask.off("progress") } uploadFile() { // 上传任务配置项 let uploadConfig = { 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 = data console.info("xx Success to request the upload. Cause: " + JSON.stringify(data)); // uploadTask = data; this.uploadTask.on("progress", (uploadedSize, totalSize) => { console.info("xx 上传进度值是:" + uploadedSize + ", 总大小:" + totalSize) }) }).catch((err) => { this.btnLabel = "文件上传失败" console.error("xx Failed to request the upload. Cause: " + JSON.stringify(err)); }) } catch (err) { this.btnLabel = "文件上传失败" console.error(`xx Invoke uploadFile failed, code is ${err.code}, message is ${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) }}
{ "module": { "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ] }}
文件上传页面就一个index.ets文件,里面包含UI和调用后端接口,代码如下:import common from "@ohos.app.ability.common";import fs from "@ohos.file.fs";import request from "@ohos.request";import hash from "@ohos.file.hash";// 获取应用文件路径let context = getContext(this) as common.UIAbilityContext;@Entry@Componentstruct Index { @State btnLabel: string = "提交文件" private uploadTask: request.UploadTask aboutToAppear() { let cacheDir = context.cacheDir; // 新建一个本地应用文件 let file = fs.openSync(cacheDir + "/test.txt", fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); fs.writeSync(file.fd, "upload file test by API9"); fs.closeSync(file); } aboutToDisappear() { this.uploadTask.off("complete") } uploadFile() { // 上传任务配置项 let uploadConfig = { 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 = data this.uploadTask.on("complete", (taskStates) => { for (let i = 0; i < taskStates.length; i++) { console.info(`xx upload complete taskState: ${JSON.stringify(taskStates[i])}`); } }); }) .catch((err) => { this.btnLabel = "文件上传失败" console.error(`xx Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`); }) } catch (err) { this.btnLabel = "文件上传失败" console.error(`xx Invoke uploadFile failed, code is ${err.code}, message is ${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) }}
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.1.RELEASE com.army file-manage 0.0.1-SNAPSHOT file-manage Demo project for Spring Boot 8 org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-web org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test commons-io commons-io 2.6 org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok
前端调用接口文件Controller代码如下:@RestController@RequestMapping("/file")@Slf4jpublic class FileController { @Autowired FileService fileService; @PostMapping("/upload") public StandardResponse upload(String fileId, MultipartHttpServletRequest multiPartRequest) { log.info("**Upload File Controller!"); FileCriteria criteria = new FileCriteria(); criteria.setFileId(fileId); try { //upload file Iterator itr = multiPartRequest.getFileNames(); MultipartFile mpf = null; while(itr.hasNext()){ mpf = multiPartRequest.getFile(itr.next()); break; } byte[] fileByteArr = null; if (null != mpf && !mpf.isEmpty()) { String originalFileName = mpf.getOriginalFilename(); log.info(originalFileName); criteria.setFileName(""); String fileExtension = FilenameUtils.getExtension(originalFileName); criteria.setFileExtension(fileExtension); fileByteArr = mpf.getBytes(); criteria.setFileByteArray(fileByteArr); criteria.setFileName(originalFileName); } } catch (IOException e) { e.printStackTrace(); log.error(e.getMessage()); } return fileService.uploadFile(criteria); }}
后端业务逻辑代码,也就是文件上传处理逻辑Service代码如下:(1)业务接口:public interface FileService { StandardResponse uploadFile(FileCriteria criteria); String saveFile(FileCriteria criteria);}
(2)业务实现类:
@Service@Slf4jpublic class FileServiceImpl implements FileService { @Value("${project.root.path}") private String rootPath = "rootPath"; @Value("${project.baseUrl}") private String baseUrl; @Override public StandardResponse uploadFile(FileCriteria criteria) { String filePath = this.saveFile(criteria); String imgPath = baseUrl + "filePath/" + filePath; StandardResponse standardResponse = new StandardResponse(); standardResponse.setSuccess(true); standardResponse.setStatusCode("100"); standardResponse.setStatusDesc("上传成功"); standardResponse.setData(imgPath); return standardResponse; } @Override public String saveFile(FileCriteria criteria) { log.info("上传文件开始!"); String pictureId = IdUtils.getId("FP"); String fileName = pictureId + "." + criteria.getFileExtension(); criteria.setFileName(fileName); String filePath = sourceFile(criteria); log.info("File Path: " + filePath); log.info("上传文件结束!"); return filePath; } private String sourceFile(FileCriteria criteria) { byte[] attachmentFileByteArray = criteria.getFileByteArray(); if (null != attachmentFileByteArray) { log.info("1.1.创建根目录."); String basePath = rootPath + this.genDatePath(); File basePathFolder = new File(basePath); if (!basePathFolder.exists()) basePathFolder.mkdirs(); log.info("根目录: " + basePath); File file = new File(basePath + File.separator + criteria.getFileName()); log.info("1.2.保存源文件 - 绝对路径: " + file.getAbsolutePath()); try { FileCopyUtils.copy(attachmentFileByteArray, file); log.info("1.3.1.保存源文件 - 保存成功 !!!"); String relativePath = this.genDatePath() + File.separator + criteria.getFileName(); return relativePath; } catch (IOException e) { log.info("1.3.2.保存源文件 - 保存失败 !!!"); file.deleteOnExit(); return ""; } } return ""; } private String genDatePath(){ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String yyyyMMdd = sdf.format(new Date()); return yyyyMMdd; }}
配置文件server: port: 8740project: root: path: /var/tomcat/file-manage/filePath/ baseUrl: http://111.114.238.134:8740/
访问域名或IP加端口访问到Thymeleaf页面,要添加一个Controller跳转@Controllerpublic class IndexController { @GetMapping("/") public String Index() { return "index"; }}
在templates目录下创建index.htm页面文件,这里的index名要和上面Controller返回“index”名一致,才能跳转过去,index.html代码如下: 文件上传 单文件上传
上面图片就是Thymeleaf页面,上传文件成功后效果。
通过此贴学习到文件上传3.0与3.1的不同处,同时也学习到了后端开发流程,其实写这个贴子之前,是一个小伙伴问到我关于文件上传问题,由于之前我写的实例里,也没有用到文件上传功能,于是我就用最新API9也就是Stage模式写了一个Demo给他参考,然后他通过参考我的Demo,学会了,可惜他现在开发的项目是用API8的,由于开发模式不一样,他遇到了问题,于是我在用API8写了一个Demo给他参考,最后他的项目也实现了文件上传。
文章相关附件可以点击下面的原文链接前往下载:
https://ost.51cto.com/resource/2729。
https://ost.51cto.com/resource/2730。
https://ost.51cto.com/resource/2731。
想了解更多关于开源的内容,请访问:
清一色开源基础软件社区
https://ost.51cto.com
标签: