HarmonyOS鸿蒙Next中使用request.uploadFile上传3MB PPT,上传的文件损坏
HarmonyOS鸿蒙Next中使用request.uploadFile上传3MB PPT,上传的文件损坏 使用request.uploadFile上传PPT文件,KB级的文件不会出现问题,但是MB级别的文件视乎有点问题,我上传3.5MB的文件,有几乎一半的概率会导致上传的文件只剩3.1MB;上传6MB的文件大概率只剩下不到4MB。我这边使用安卓上传这些文件都是没有问题的,鸿蒙这边上传不知道为什么会导致文件损坏,后续我用web打开PPT失败。
对比一下官方上传文件的代码,看看有啥地方写错了吗?
async requestUploadFile(fileName: string, callback: (progress: number, isSuccess: boolean) => void,
context: common.UIAbilityContext) {
// 获取应用文件路径
// 请在组件内获取context,确保this.getUIContext().getHostContext()返回结果为UIAbilityContext
let url = await urlUtils.getUrl(context);
let cacheDir = context.cacheDir;
// 新建一个本地应用文件
try {
let file = fs.openSync(cacheDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
fs.writeSync(file.fd, 'upload file test');
fs.closeSync(file);
} catch (error) {
let err: BusinessError = error as BusinessError;
logger.error(TAG, `Invoke uploadFile failed, code=${err.code}, message=${err.message}`);
}
// 上传任务配置项
let files: request.File[] = [
//uri前缀internal://cache 对应cacheDir目录
{
filename: fileName,
name: 'test',
uri: 'internal://cache/' + fileName,
type: 'txt'
}
]
let data: request.RequestData[] = [{ name: 'name', value: 'value' }];
let uploadConfig: request.UploadConfig = {
url: url,
header: {
'key1': 'value1',
'key2': 'value2'
},
method: 'POST',
files: files,
data: data
}
// 将本地应用文件上传至网络服务器
try {
request.uploadFile(context, uploadConfig)
.then((uploadTask: request.UploadTask) => {
uploadTask.on('complete', (taskStates: Array<request.TaskState>) => {
for (let i = 0; i < taskStates.length; i++) {
logger.info(TAG, `upload complete taskState: ${JSON.stringify(taskStates[i])}`);
}
callback(100, true);
});
})
.catch((err: BusinessError) => {
logger.error(TAG, `Invoke uploadFile failed, code=${err.code}, message=${err.message}`);
})
} catch (error) {
let err: BusinessError = error as BusinessError;
logger.error(TAG, `Invoke uploadFile failed, code=${err.code}, message=${err.message}`);
}
}
更多关于HarmonyOS鸿蒙Next中使用request.uploadFile上传3MB PPT,上传的文件损坏的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
我在上传一些小文件都是正常的,几乎不会出现问题。我的代码在运行的时候也没见啥报错提示。还有我用的是request.uploadfile,可能跟你的方法不太一样,我这边对接后端的接口,
改成request.uploadfile了~~,
好的,谢谢你,已经解决了。不小心写了个小错误,
👍
可以给大家看看我上传部分的代码,我本人没发现什么问题
uploadPPTFn(fileUrl: string): void {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
let uploadTask: request.UploadTask;
let fileName = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
this.fileName = decodeURI(fileName)
this.uploadTitle = this.fileName
let newpath = context.cacheDir + "/"+fileName//+".pptx";
fs.open(fileUrl,2).then((file: fs.File) => {
console.info("file fd: " + file.fd);
fs.copyFile(file.fd, newpath, (err: BusinessError) => {
if (err) {
this.uploadStatus = 'fault'
console.error("copy file failed with error message: " + err.message + ", error code: " + err.code);
return
} else {
console.info("copy file succeed");
}
fs.closeSync(file);
});
}).catch((err: BusinessError) => {
this.uploadStatus = 'fault'
console.error("open file failed with error message: " + err.message + ", error code: " + err.code);
return
});
//获取文件大小
this.getFileSize(newpath);
let realuri = "internal://cache/" + newpath.split("cache/")[1]//.split(".pptx")[0]+".pptx";
console.log('applog:realuri' + realuri);
//获取了沙箱真实internal格式路径,继续对照准备参数
let uploadConfig: request.UploadConfig = {
url: Const.G_AjaxApi_activity + "/api/ai/uploadPPT", // HTTP协议地址
header: { "Content-Type": "multipart/form-data" },
method: "POST",
files: [{
filename: fileName,
name: "file",
uri: realuri,
type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
}], // 建议type填写HTTP协议规范的MIME类型
data: [{ name: "guid", value: this.guid },
{ name: "appID", value: this.appId.toString() },
{ name: "presentations_id", value: this.presentations_id.toString()},
{ name: "provinces", value: this.province },],
};
try {
request.uploadFile(getContext(this), uploadConfig).then((data:request.UploadTask) => {
uploadTask = data;
console.log('上传文件成功:');
uploadTask.on("complete",(data)=>{
console.log("上传完成:"+JSON.stringify(data))
})
uploadTask.on("headerReceive",(data)=>{
console.log("headerReceive"+JSON.stringify(data))
let result:uploadResponse = data as uploadResponse
console.log("***"+result.body)
let tempUrl = result.body.split('url":"')[1]
let tempName = tempUrl.split('","name":"')[1]
let tempOssPath = tempName.split('","ossPath":"')[1]
let tempPresentations_id = tempOssPath.split('","presentations_id":')[1]
tempUrl = tempUrl.split('","name":"')[0]
tempName = tempName.split('","ossPath":"')[0]
tempOssPath = tempOssPath.split('","presentations_id":')[0]
tempPresentations_id = tempPresentations_id.split(',')[0]
this.uploadData.url = tempUrl
this.uploadData.name = tempName
this.uploadData.ossPath = tempOssPath
this.uploadData.presentations_id = Number.parseInt(tempPresentations_id)
this.uploadStatus = 'complete'
console.log("PPT上传全过程结束"+JSON.stringify(this.uploadData))
})
}).catch((e: BusinessError) => {
this.uploadStatus = 'fault'
console.error('Failed to request the upload. Cause: ' + JSON.stringify(e));
});
} catch (err) {
this.uploadStatus = 'fault'
console.error('applog:' + JSON.stringify(err));
console.error('err.code : ' + err.code + ', err.message : ' + err.message);
}
}
在HarmonyOS Next中,request.uploadFile 在处理较大文件时出现损坏,通常与文件分片、流处理或网络请求配置有关。以下排查方向供参考:
-
检查文件读取方式:确保使用正确的API读取文件,避免在读取过程中截断。对于二进制文件(如PPT),建议使用
fs.openSync和fs.readSync以二进制模式读取,或直接使用file对象(如picker返回的Uri文件对象)作为uploadFile的file参数。 -
验证分片上传逻辑:如果自行实现了分片上传,需确认分片大小计算、切片边界处理是否正确。HarmonyOS Next的文件API可能与其他平台存在差异,建议使用系统推荐的分片方法(如
fs.createStream处理流)。 -
排查网络请求超时与缓冲区:检查
request的connectTimeout或header配置,确保服务器支持大文件上传。部分网络库在默认配置下可能限制请求体大小,可尝试调整timeout或使用data字段分段发送。 -
对比服务器接收逻辑:确认服务器端接收文件的代码是否兼容HarmonyOS的上传格式(如
multipart/form-data边界处理)。建议通过抓包工具(如Charles)对比鸿蒙与安卓的上传请求体,查看数据是否完整。 -
使用最新SDK与工具:确保DevEco Studio和HarmonyOS SDK已更新至最新版本,早期版本可能存在文件上传相关的已知问题。
若以上步骤仍无法解决,可尝试简化代码:仅上传纯二进制文件(如图片)测试,以排除PPT文件格式或内容的特定影响。


