在日常开发过程中,将数据导出到Excel是常见的一种需求。爱车记App有个数据导出功能,可以将用户的充电记录导出Excel,因为Harmony OS Next的沙盒机制,默认导出的文件只能保存到App自己的目录中,为了方便用户保存数据,我们可以通过文件分享功能,用户可以将文件保存到手机的任意位置。
一、后端导出Excel文件
后端代码我们不做过多介绍,就是使用EasyExcel
导出Excel文件并下载。
/**
* 数据导出
*
* @throws IOException IO异常
*/
@GetMapping(value = "export", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void export() throws IOException {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletResponse response = null;
HttpServletRequest request = null;
if (servletRequestAttributes != null) {
response = servletRequestAttributes.getResponse();
request = servletRequestAttributes.getRequest();
}
if (response == null) {
throw new CustomException("未获取到用户信息");
}
response.setContentType("application/x-msdownload");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("充电记录.xlsx", "UTF-8"));
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
// 创建excel对象
CarUser user = tokenUtil.getLoginUser(request);
List<CarEnergyExportVO> carEnergyList4Export = carEnergyService.selectCarEnergyList4Export(user.getId());
//内容样式策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
//垂直居中,水平居中
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
//设置 自动换行
contentWriteCellStyle.setWrapped(true);
// 字体策略
WriteFont contentWriteFont = new WriteFont();
// 字体大小
contentWriteFont.setFontHeightInPoints((short) 12);
contentWriteFont.setFontName("仿宋");
contentWriteCellStyle.setWriteFont(contentWriteFont);
//头策略使用默认 设置字体大小
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short) 12);
headWriteFont.setFontName("仿宋");
headWriteCellStyle.setWriteFont(headWriteFont);
headWriteCellStyle.setFillForegroundColor(IndexedColors.TAN.getIndex());
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), CarEnergyExportVO.class)
.registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle))
.build();
//创建sheet
WriteSheet writeSheet = EasyExcel.writerSheet("充电记录").head(CarEnergyExportVO.class).build();
//导出
excelWriter.write(carEnergyList4Export, writeSheet);
excelWriter.finish();
}
二、下载文件
文件下载我们调用downloadFile(context: BaseContext, config: DownloadConfig)
方法,context
是上下文信息,DownloadConfig
是参数信息,其中url
是我们的后台地址,filePath
是文件保存到本地的路径,header
是传递到后端的头部信息,比如我这里的token
是传递的认证信息。
在下载文件的回调方法中,我们监听downloadTask
事件,complete
代表文件下载完成,文件下载文成后,调用分装的公共的文件分享方法shareFile
对文件进行分享。
IBestToast.show({
icon: $r("app.media.mine_exporting_data"),
message: getStringFromResource($r("app.string.exporting"))
})
try {
// 判断文件是否存在,存在就删除
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;
let path = filesDir + '/爱车记.xlsx';
if (fs.accessSync(path)) {
fs.unlinkSync(path);
}
request.downloadFile(context, {
url: Constants.API + '/common/export',
filePath: path,
header: {
"token": PreferencesUtil.readDataSync<string>("token")
}
}).then((downloadTask: request.DownloadTask) => {
downloadTask.on('complete', () => {
IBestToast.hide()
shareFile(path)
// let file = fs.openSync(filesDir + '/car_expense.xlsx', fs.OpenMode.READ_WRITE);
// let arrayBuffer = new ArrayBuffer(1024);
// let readLen = fs.readSync(file.fd, arrayBuffer);
// let buf = buffer.from(arrayBuffer, 0, readLen);
// console.info(`The content of file: ${buf.toString()}`);
// fs.closeSync(file);
})
}).catch((err: BusinessError) => {
IBestToast.hide()
console.error(`Invoke downloadTask failed, code is ${err.code}, message is ${err.message}`);
});
} catch (error) {
IBestToast.hide()
let err: BusinessError = error as BusinessError;
console.error(`Invoke downloadFile failed, code is ${err.code}, message is ${err.message}`);
}
三、文件分享方法
文件分享时,我们传递文件的路径,这里有两个注意事项:
action
:这个地方我们需要使用ohos.want.action.viewData
,如果调用ohos.want.action.sendData
,会使用默认的程序打开,比如我这里是Excel文件,如果安装了WPS,会直接调用WPS打开
type
:这个是MIME Type,比如Excel 2007后续版本(xlsx后缀)默认为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
/**
* 分享文件
*/
export async function shareFile(filePath: string) {
let context = AppStorage.get('context') as common.UIAbilityContext;
// 获取文件沙箱路径
// let filePath = this.context.filesDir + '/test.txt';
// 将沙箱路径转换为 URI
let uri = fileUri.getUriFromPath(filePath);
// 创建分享意图
let want: Want = {
flags: wantConstant.Flags.FLAG_AUTH_WRITE_URI_PERMISSION | wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION,
action: 'ohos.want.action.viewData',
uri: uri,
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
};
// 启动分享
context.startAbility(want)
.then(() => {
console.log('Share file successfully');
})
.catch((err: BusinessError) => {
console.error('Failed to share file:', err);
});
}
四、配置权限
为了实现分享,我们需要在模块下的module.json5
文件中配置相应的权限,在skills
的uris
添加如下内容
{
"scheme": "file",
"host": "*",
"path": "/storage/*"
}
评论 (0)