更新记录
1.0.3(2026-11-04) 下载此版本
修复了一些问题
1.0.2(2026-03-25) 下载此版本
优化移动端返回路径
1.0.1(2026-02-24) 下载此版本
新增x-file-picker 组件
查看更多平台兼容性
uni-app(4.0)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | - | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
x-native-uploader 原生文件上传组件
x-native-uploader 是一个跨平台的文件上传组件,专为解决 UniApp 在 App 端文件选择与上传的痛点而设计。它集成了 Native.js 的能力,支持在 Android 和 iOS 上调用原生文件选择器,同时兼容 H5 和小程序平台。
功能特性
- 📱 原生体验: App 端使用 Native.js 调用系统原生文件选择器 (Intent / UIDocumentPicker),支持选择任意类型文件。
- 🚀 高性能上传: 默认使用
uni.uploadFile,进度回调连续;可切换到plus.uploader原生上传(适合超大文件后台传输)。 - 🔄 跨平台兼容: 自动降级处理,H5 使用
uni.chooseFile,小程序使用uni.chooseMessageFile,一套代码多端运行。 - 📦 多选支持: 支持一次选择多个文件进行批量上传 (Android/iOS/H5/MP),并受
limit约束。 - 🛠️ 灵活配置: 支持自定义上传 URL、Header、FormData 以及自定义触发按钮 UI。
- 📄 PDF 及其他文件支持: 通过
ContentResolver把 Android 的content://URI 落盘到应用沙盒再上传,彻底规避file not found。 - 🗑️ 单条管理: 每个文件支持删除、取消、失败重试,删除时自动中止任务并清理临时文件。
引入组件
import xNativeUploader from '@/components/x-native-uploader/x-native-uploader.vue';
export default {
components: {
xNativeUploader
}
}
代码演示
基础用法 (单选)
默认点击按钮选择单个文件并自动上传。
<x-native-uploader
url="https://your-api.com/upload"
:header="{ 'Authorization': 'Bearer token' }"
:formData="{ userId: '123' }"
@success="onSuccess"
@fail="onFail"
></x-native-uploader>
多文件上传
设置 multiple 属性开启多选,limit 控制最大选择数量。
<x-native-uploader
url="https://your-api.com/upload"
:multiple="true"
:limit="9"
fileType="all"
@success="onSuccess"
@fail="onFail"
>
<view class="custom-btn">
<text>点击批量上传文件</text>
</view>
</x-native-uploader>
PDF 文件上传(Android 兼容)
设置 fileType="all" 即可支持上传 PDF 文件,组件会把 Android 平台的 content:// URI 落盘后再上传:
<x-native-uploader
url="https://your-api.com/upload/pdf"
fileType="all"
trigger-text="上传 PDF 文件"
@success="handlePdfUploadSuccess"
@fail="handleUploadFail"
>
</x-native-uploader>
自定义触发按钮
通过默认插槽 (slot) 自定义上传按钮样式。
<x-native-uploader url="...">
<button type="primary">点击上传</button>
</x-native-uploader>
API
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
url |
上传接口地址 (必填) | String |
- |
name |
上传文件的字段名 | String |
'file' |
header |
请求头对象 | Object |
{} |
formData |
额外的上传参数 | Object |
{} |
fileType |
文件选择类型,可选值: image, video, all |
String |
'image' |
multiple |
是否开启多选 | Boolean |
false |
limit |
最大文件数量 (含已上传的,超出会提示) | Number |
9 |
autoUpload |
选择文件后是否自动上传 | Boolean |
true |
disabled |
是否禁用选择 | Boolean |
false |
triggerText |
默认触发按钮文案 | String |
'选择文件并上传' |
nativeUpload |
是否用 plus.uploader 原生上传(默认 uni.uploadFile,进度更连续) |
Boolean |
false |
Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
success |
上传成功时触发 | { file: FileObj, response: Any, raw: Object } |
fail |
上传失败时触发 | { file: FileObj, error: Any } |
progress |
上传进度更新时触发 | { file: FileObj, progress: Number, percent: Number }(progress 为整体进度,percent 为纯上传进度) |
remove |
删除列表中的某个文件时触发 | { file: FileObj, index: Number } |
Methods(通过 ref 调用)
| 方法 | 说明 |
|---|---|
clear() |
中止所有上传并清空文件列表 |
FileObj 数据结构
{
uid: 1, // 唯一标识(列表 key,删除后不会错位)
path: "...", // 原始路径,可能是 content://
localPath: "...", // 实际用于上传的本地绝对路径(沙盒副本)
uploadName: "...", // 落盘并随请求发送的文件名
name: "...", // 列表展示的文件名(保留用户选择的原名)
size: 10240, // 字节数
progress: 100, // 进度 (0-100),含准备阶段
status: "success", // 状态: pending, uploading, success, error, cancelled
statusText: "..." // 状态描述文本
}
success 回调数据结构
onSuccess(e) {
e.file; // 上传完成后的 FileObj
e.response; // 服务端返回体,已自动 JSON.parse;解析失败则是原始字符串
e.raw; // uni.uploadFile 的原始返回 { data, statusCode, errMsg }
}
真实回调示例(App 端选择 Excel 上传):
{
"file": {
"uid": 1,
"path": "content://media/external/file/35",
"localPath": "/storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/doc/uploader/终端产品线-花名册.xlsx",
"uploadName": "终端产品线-花名册.xlsx",
"name": "终端产品线-花名册.xlsx",
"size": 8399,
"progress": 100,
"status": "success",
"statusText": "上传成功",
"error": ""
},
"response": {
"strings": {
"userId": "1001",
"source": "app"
},
"error": "0",
"files": {
"file": {
"name": "终端产品线-花名册.xlsx",
"url": "files/终端产品线-花名册.xlsx",
"type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"size": 8399
}
}
},
"raw": {
"data": "{\"strings\":{\"userId\":\"1001\",\"source\":\"app\"},\"error\":\"0\",\"files\":{\"file\":{\"name\":\"终端产品线-花名册.xlsx\",\"url\":\"files/终端产品线-花名册.xlsx\",\"type\":\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\"size\":8399}}}",
"statusCode": 200,
"errMsg": "uploadFile:ok"
}
}
说明:
response已经是对象,业务判断直接写if (e.response.error === '0'),不用再JSON.parse(e.response)。raw.statusCode在 200~299 之间才会触发,其余状态码和网络错误都走@fail。response.strings是服务端回显的formData,response.files是服务端保存的文件信息。- 服务端 multipart 收到的 filename 与
file.uploadName一致;落盘时保留原始文件名,仅在同名冲突时追加 6 位后缀(如花名册_112006.xlsx)。
注意事项
- Android 权限: App 端需要
READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限。 - iOS 配置: iOS 端无需特殊配置,使用
UIDocumentPickerViewController。 - H5 跨域: 确保上传接口支持 CORS 跨域请求。
- 小程序: 微信小程序使用
uni.chooseMessageFile,支持从聊天记录中选择文件。 - Android content:// URI 处理: 组件不再把
content://直接丢给上传器,而是通过ContentResolver.openInputStream()把文件内容复制到应用沙盒的_doc/uploader/目录,用真实文件路径上传,因此不会出现file not found。上传成功后会自动清理沙盒里的临时副本。 - 文件格式支持: 当
fileType="all"时,支持选择任意类型文件,但上传前请确保服务器端支持该文件格式。文件名缺少扩展名时会根据 MIME 自动补全(如application/pdf→.pdf)。
常见问题
Q: 为什么在 Android 上选择 PDF 文件后上传失败(file not found)?
A: 因为系统返回的是 content:// 形式的 URI,它不是真实文件路径,Android 10+ 的分区存储下普通上传器也读不了。组件现在的处理流程是:
x-file-picker返回content://原始 URI 和文件名;x-native-uploader用ContentResolver打开输入流,分块复制到_doc/uploader/;- 用沙盒里的真实路径上传,成功后自动删除副本。
如果仍然失败,请检查:
- 是否在真机上测试(模拟器的
content://兼容性较差); - 查看控制台
[x-native-uploader]开头的日志,确认落盘是否成功; - 服务器端是否支持该文件格式及大小。
Q: 进度条为什么之前一直不动?
A: plus.uploader 的 statechanged 事件只在上传状态切换时触发,拿不到连续的字节进度,所以进度会从 0 直接跳到 100。现在默认使用 uni.uploadFile(onProgressUpdate 每帧回调),并保留了 nativeUpload 模式(内部用定时器轮询 uploadedSize/totalSize 补齐进度)。
Q: 为什么选完文件要点一下才显示进度?
A: Android 的 content:// 文件需要先复制到应用沙盒才能上传,大文件复制时会占用主线程。组件现在的处理方式是:
- 先把状态切成「准备文件中...」并渲染到屏幕上(不会出现无反馈的卡顿);
- 复制时按 40ms 时间片让出主线程,状态同步更新成「准备文件中 65%」;
- 复制完成后立刻切到「上传中 x%」。
进度条在准备阶段占 0~30%,上传阶段占 30~100%,全程只增不减。@progress 回调里的 progress 是整体进度,percent 是纯上传进度。
Q: 可以删除单个文件吗?
A: 可以。列表每一项右侧都有「删除」按钮,删除时会自动中止正在进行的上传任务、清理沙盒副本,并触发 remove 事件。上传失败的项还可以点「重试」,上传中的项可以点「取消」。
Q: 如何限制只能上传特定类型的文件?
A: 可以通过设置 fileType 属性来限制文件类型:
fileType="image"- 仅允许选择图片fileType="video"- 仅允许选择视频fileType="all"- 允许选择所有类型文件

收藏人数:
下载插件并导入HBuilderX
赞赏(6)
下载 466
赞赏 6
下载 12753694
赞赏 1959
赞赏
京公网安备:11010802035340号