HarmonyOS 7 / API 26 ArkWeb 文件上传适配:内核差异、权限边界和失败兜底一次验清

HarmonyOS 7 / API 26 里用 ArkWeb 承载 H5 页面时,文件上传是一个很容易被低估的适配点。H5 页面里一个普通的 `<input type="file">`,在桌面浏览器里基本不会出问题,但放进应用之后,就会遇到权限、文件类型、回调生命周期、页面恢复和上架审核这些边界。
我一般不会只问“能不能选文件”。更稳的检查方式是:能不能选到正确类型,取消选择有没有兜底,页面切后台后回调还在不在,上传失败后用户能不能重试,应用权限声明和实际触发时机是否一致。
问题先拆开
ArkWeb 文件上传至少有四个风险点:
- H5 允许的文件类型和应用实际能提供的文件类型不一致;
- 用户取消选择以后,页面没有收到明确结果;
- 选择文件时应用进入后台,回来后回调对象已经失效;
- 页面要求上传敏感文件,但应用权限声明和说明不清楚。
这些问题单独看都不复杂,放到一起就会变成“线上偶现上传失败”。所以我会先把上传流程当成一个独立能力来验,而不是等业务页面写完再补。
案例一:文件类型没有收口
H5 里常见写法是这样:
<input type="file" accept="image/*,.pdf" />
这段代码只是在 H5 侧表达意图,不等于应用侧一定正确处理了类型。比如页面只想要图片和 PDF,但应用侧没有做白名单,最后可能把视频、压缩包或者不支持的文件也传进来。
我会在应用侧先定义一个类型白名单:
type UploadScene = 'avatar' | 'feedback' | 'document'
type UploadRule = {
scene: UploadScene
mimeTypes: string[]
maxSizeMb: number
}
const uploadRules: UploadRule[] = [
{ scene: 'avatar', mimeTypes: ['image/png', 'image/jpeg'], maxSizeMb: 5 },
{ scene: 'feedback', mimeTypes: ['image/png', 'image/jpeg', 'video/mp4'], maxSizeMb: 30 },
{ scene: 'document', mimeTypes: ['application/pdf'], maxSizeMb: 20 },
]
然后统一检查:
class UploadRuleChecker {
check(scene: UploadScene, file: { mimeType: string; sizeMb: number }): string[] {
const rule = uploadRules.find(item => item.scene === scene)
const errors: string[] = []
if (!rule) {
return ['上传场景没有配置规则']
}
if (!rule.mimeTypes.includes(file.mimeType)) {
errors.push(`文件类型 ${file.mimeType} 不在白名单内`)
}
if (file.sizeMb > rule.maxSizeMb) {
errors.push(`文件大小 ${file.sizeMb}MB 超过 ${rule.maxSizeMb}MB`)
}
return errors
}
}
这一步不是为了把逻辑写复杂,而是为了让 H5、ArkWeb 回调和应用上传策略对齐。文件类型不对,越早挡住越好。
案例二:取消选择和后台恢复没有兜底
另一个常见问题是用户点了上传入口,但是没有真正选文件。可能是用户取消,也可能是切后台后流程被打断。如果页面一直等回调,就会卡在“上传中”。
我会给每一次选择分配一个请求 id:
class WebFileSelectGuard {
private activeRequestId = ''
start(): string {
this.activeRequestId = `${Date.now()}-${Math.random()}`
return this.activeRequestId
}
isActive(id: string): boolean {
return this.activeRequestId === id
}
cancel(id: string) {
if (this.isActive(id)) {
this.activeRequestId = ''
}
}
}
回调处理时先判断请求是否还有效:
async handleFileResult(requestId: string, files: UploadFile[]) {
if (!this.fileSelectGuard.isActive(requestId)) {
return
}
if (files.length === 0) {
this.showUploadState('cancelled')
return
}
const errors = this.ruleChecker.check('feedback', files[0])
if (errors.length > 0) {
this.showUploadError(errors.join('\n'))
return
}
await this.upload(files[0])
}
这样用户取消、页面销毁、后台恢复后的旧回调,都不会继续改当前页面状态。
用脚本检查上传规则
下面这个脚本可以直接跑,用来检查上传配置有没有明显漏洞:
const rules = [
{ scene: 'avatar', mimeTypes: ['image/png', 'image/jpeg'], maxSizeMb: 5 },
{ scene: 'feedback', mimeTypes: ['image/png', 'image/jpeg', 'video/mp4'], maxSizeMb: 30 },
{ scene: 'document', mimeTypes: ['application/pdf'], maxSizeMb: 20 },
]
const cases = [
{ scene: 'avatar', file: { mimeType: 'image/png', sizeMb: 2 } },
{ scene: 'avatar', file: { mimeType: 'video/mp4', sizeMb: 2 } },
{ scene: 'document', file: { mimeType: 'application/pdf', sizeMb: 28 } },
]
function checkUploadCase(item) {
const rule = rules.find(rule => rule.scene === item.scene)
const errors = []
if (!rule) {
errors.push('缺少场景规则')
return { ...item, passed: false, errors }
}
if (!rule.mimeTypes.includes(item.file.mimeType)) {
errors.push('文件类型不允许')
}
if (item.file.sizeMb > rule.maxSizeMb) {
errors.push('文件大小超限')
}
return { ...item, passed: errors.length === 0, errors }
}
const result = cases.map(checkUploadCase)
console.log(JSON.stringify({
total: result.length,
failed: result.filter(item => !item.passed).length,
result,
}, null, 2))
输出里应该有两个失败用例:
{
"total": 3,
"failed": 2
}
一个是头像场景不允许视频,一个是 PDF 文件超过大小限制。这个脚本能提前把配置问题拦住,不要等用户上传失败以后才发现。
几种兜底方式对比
| 方案 | 好处 | 问题 | 适合场景 |
| H5 自己处理 accept | 接入快 | 应用侧不可控,边界不清楚 | 简单内部页面 |
| 应用侧统一白名单 | 类型和大小明确 | 需要维护规则 | 生产应用 |
| 场景化上传规则 | 最清楚,便于审核和排查 | 前期设计成本更高 | 多页面、多文件类型上传 |
我更倾向第三种。上传不是一个按钮,而是一组规则:场景、类型、大小、取消、失败、重试、权限说明,都应该放到同一个模型里。
发布前检查清单
| 检查项 | 合格标准 |
| 文件类型 | H5 accept 和应用白名单一致 |
| 文件大小 | 每个场景都有明确上限 |
| 取消选择 | 用户取消后页面不会一直 loading |
| 后台恢复 | 旧回调不会覆盖新状态 |
| 失败兜底 | 上传失败能重试,错误提示清楚 |
| 审核说明 | 权限触发时机和使用目的能解释清楚 |
后面怎么避免
我会把 ArkWeb 文件上传当成应用能力来做,而不是当成 H5 的一个输入框:
- 每个上传入口先定义场景;
- 每个场景配置文件类型和大小上限;
- 每次选择文件都有 requestId;
- 用户取消和页面销毁都要有明确状态;
- 上传失败保留重试入口;
- 上架前检查权限说明和实际触发是否一致。
这样处理以后,ArkWeb 上传问题会从“偶现不好复现”变成“有规则、有日志、有兜底”的普通问题。后面无论是图片、反馈附件还是文档上传,都可以复用同一套检查方式。
更多推荐


所有评论(0)