0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙上实现文件上传功能

OpenHarmony技术社区 来源:OST开源开发者 作者:OST开源开发者 2023-05-22 10:51 次阅读

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

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

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

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

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

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

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

效果如下:

b12abf04-f7fb-11ed-90ce-dac502259ad0.gif

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
@Component
structIndex{
@StatebtnLabel:string='提交文件'
privateuploadTask:request.UploadTask

aboutToAppear(){
//获取应用文件路径
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=data
console.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
@Component
structIndex{
@StatebtnLabel:string='提交文件'
privateuploadTask:request.UploadTask

aboutToAppear(){
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=data
this.uploadTask.on('complete',(taskStates)=>{
for(leti=0;i< taskStates.length; i++) {
              console.info(`xx upload complete taskState: ${JSON.stringify(taskStates[i])}`);
            }
          });
        })
        .catch((err) =>{
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.0

org.springframework.boot
spring-boot-starter-parent
2.3.1.RELEASE
 

com.army
file-manage
0.0.1-SNAPSHOT
file-manage
DemoprojectforSpringBoot

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")
@Slf4j
publicclassFileController{
@Autowired
FileServicefileService;

@PostMapping("/upload")
publicStandardResponseupload(StringfileId,MultipartHttpServletRequestmultiPartRequest){
log.info("**UploadFileController!");

FileCriteriacriteria=newFileCriteria();
criteria.setFileId(fileId);

try{
//uploadfile
Iteratoritr=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
@Slf4j
publicclassFileServiceImplimplementsFileService{
@Value("${project.root.path}")
privateStringrootPath="rootPath";
@Value("${project.baseUrl}")
privateStringbaseUrl;

@Override
publicStandardResponseuploadFile(FileCriteriacriteria){
StringfilePath=this.saveFile(criteria);
StringimgPath=baseUrl+"filePath/"+filePath;

StandardResponsestandardResponse=newStandardResponse();
standardResponse.setSuccess(true);
standardResponse.setStatusCode("100");
standardResponse.setStatusDesc("上传成功");
standardResponse.setData(imgPath);
returnstandardResponse;
}

@Override
publicStringsaveFile(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:8740

project:
root:
path:/var/tomcat/file-manage/filePath/
baseUrl:http://111.114.238.134:8740/
访问域名或 IP 加端口访问到 Thymeleaf 页面,要添加一个 Controller 跳转。
@Controller
publicclassIndexController{

@GetMapping("/")
publicStringIndex(){
return"index";
}
}

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

index.html 代码如下:


单文件上传

b143884a-f7fb-11ed-90ce-dac502259ad0.png

b1562b6c-f7fb-11ed-90ce-dac502259ad0.png

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

总结

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

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    7640

    浏览量

    148512
  • API
    API
    +关注

    关注

    2

    文章

    1383

    浏览量

    60994
  • 开发者
    +关注

    关注

    1

    文章

    499

    浏览量

    16392
  • 鸿蒙
    +关注

    关注

    55

    文章

    1637

    浏览量

    42122
  • HarmonyOS
    +关注

    关注

    79

    文章

    1853

    浏览量

    29267

原文标题:鸿蒙上实现“文件上传”功能

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    这个CMS系统可以同时选择多个文件上传,是怎么实现的?

    我发现有个CMS系统, 叫网站快车,他有一个指上传功能,能框选多个文件,同时上传上传中有进度显示,这个是怎么作到的?大家看,他这里可以这样选择图片。然后把
    发表于 02-09 17:13

    如何使用DGUS II的数据自动上传功能

    使用DGUS II时,如果想要实现数据自动上传,需要注意以下几点:1. 在软件中勾选“数据自动上传功能”,或者用“按键值返回”控件代替“基本触控”控件;勾选的地方在如下图:2. 在CFG文件
    发表于 01-02 20:52

    Linux下如何实现断点续传功能

    在Linux系统上传和下载文件的时候,由于网络问题或文件过大,很容易断开,从头上传十分费时费力,那么可以实现从下载的断开点继续开始传送吗?这
    发表于 02-06 17:14

    利用java语言实现文件上传功能

    本文首先介绍了java 中的文件处理类,然后在参考了RFC 文件的基础上,对上传文件的信息格式进行了详细的介绍。最后结合实际,利用Jakarta Commons 项目的一个组件comm
    发表于 09-15 15:48 37次下载

    基于Iframe内联框架的异步文件上传与删除

    在Weh应用程序开发过程中,文件上传功能是个很常用又非常重要的功能,它要处理的内容主要包括:如何将上传文件
    发表于 11-11 10:20 5次下载
    基于Iframe内联框架的异步<b class='flag-5'>文件</b><b class='flag-5'>上传</b>与删除

    如何在java上传和下载文件

    文件上传在web应用中非常普遍,要在jsp环境中实现文件上传功能是非常容易的,因为网上有许多用java开发的
    发表于 11-13 08:00 11次下载

    java Web如何实现文件上传与下载

    文件上传概述,实现web开发中的文件上传功能,需完成如下二步操作: 在web页面中添加上传输入
    发表于 03-06 11:03 7次下载
    java Web如何<b class='flag-5'>实现</b><b class='flag-5'>文件</b>的<b class='flag-5'>上传</b>与下载

    Verizon宣布在所有5G市场开启5G上传功能

    据国外媒体报道,Verizon已宣布在所有5G市场开启5G上传功能,为人们上传高清视频以及玩大型在线多人游戏提供更快的速度。
    发表于 05-21 11:54 398次阅读

    如何把鸿蒙文件上传到python服务器端

    1.首先鸿蒙的js文件上传,设置目录路径为: 构建路径在工程主目录下: 该目录的说明见下面描述: 视图构建如下: 界面代码: div class="container" div onclick
    的头像 发表于 04-16 15:02 1765次阅读
    如何把<b class='flag-5'>鸿蒙</b>的<b class='flag-5'>文件</b><b class='flag-5'>上传</b>到python服务器端

    鸿蒙上使用Python进行物联网编程

    在上一篇帖子《使用 Python 开发鸿蒙设备程序(1-GPIO 外设控制)》中,已经成功的使用 Python 对 GPIO 上的外设进行了控制。 这其实不是什么大不了的事,从功能的角度也着实不值得
    的头像 发表于 09-28 09:55 3733次阅读
    在<b class='flag-5'>鸿蒙上</b>使用Python进行物联网编程

    鸿蒙上安装按钮实现下载、暂停、取消、显示等操作

    今天给大家分享在鸿蒙上一个按钮实现下载、暂停、取消、显示下载进度操作。
    的头像 发表于 01-04 14:32 1847次阅读

    如何使用DGUS II的数据自动上传功能

    使用DGUS II时,如果想要实现数据自动上传,需要注意以下几点:  (1) 在软件中勾选“数据自动上传功能”,或者用“按键值返回”控件代替“基本触控”控件;  勾选的地方在如下图红色框选位置
    发表于 01-18 15:05 662次阅读
    如何使用DGUS II的数据自动<b class='flag-5'>上传功能</b>

    鸿蒙上实现“数字华容道”小游戏

    本篇文章教大家如何在鸿蒙上实现“数字华容道”小游戏。
    的头像 发表于 12-26 09:52 873次阅读

    鸿蒙上开发“小蜜蜂”游戏

    小时候我们有个熟悉的游戏叫小蜜蜂。本文教大家在鸿蒙上学做这个小蜜蜂游戏。
    的头像 发表于 04-03 11:27 1252次阅读

    前端文件上传的几种交互造轮子

    可以用剪贴板功能让自己的 cv 实现文件上传,于是自己就整合了目前几种文件上传的交互方式,码了一
    的头像 发表于 07-04 10:39 346次阅读