当前位置: 首页 > article >正文

【vue】Uniapp 打包Android 文件选择上传问题详解~

需求

uniapp兼容android app,pc,h5的文件选择并上传功能。

需要支持拍照和相册选择,以及选择其他类型文件上传~

实践过程和问题

开始使用uni-file-picker组件

以为很顺利,android模拟器测试……

忽略了平台兼容性提示~😭

Get:上传图片或拍照,使用uniapp自带的uni.chooseImage即可……

还需要上传非媒体问题(图片、音频、影片)。本以为uni.chooseFile就OK了~

But

提示

uniapp提示:Android端可以使用Native.js

  • App端如需选择非媒体文件,可在插件市场搜索文件选择,其中Android端可以使用Native.js,无需原生插件,而iOS端需要原生插件。
  • App端如果想选择下载到_doc、_downloads、_documents等plus.io控制的目录下的文件,可通过plus.io Api,自己做选择框。

官方提示到此为止~

AI求解

于是,开始了漫长的AI问答……

deepseek、豆包、文心全问一遍~(其实内核是不是都deepseek🙂)

都”快速“给出答案代码,然而”打包“测试已经没反应;好一点的依旧只能选图片~

举一个栗子~

问:Android端使用Native.js进行选择文件上传

答:

1. 配置权限

manifest.json文件中配置文件读取权限:


{"plus": {"permission": {"readExternalStorage": {"desc": "读取设备外部存储空间的文件","android": {"name": "android.permission.READ_EXTERNAL_STORAGE"}}}}
}

2. 编写选择文件的 Native.js 代码

在页面的<script>标签内或单独的 JS 文件中编写选择文件的逻辑:


function pickFile(callback) {const Intent = plus.android.importClass('android.content.Intent');const intent = new Intent(Intent.ACTION_GET_CONTENT);intent.addCategory(Intent.CATEGORY_OPENABLE);// 设置选择所有类型文件intent.setType('*/*'); plus.android.startActivityForResult(intent, function (intentData) {if (intentData) {const uri = intentData.getData();const ContentResolver = plus.android.importClass('android.content.ContentResolver');const cursor = plus.android.invoke(plus.android.runtimeMainActivity, 'getContentResolver').query(uri, ['_data'], null, null, null);if (cursor.moveToFirst()) {const columnIndex = cursor.getColumnIndex('_data');const filePath = cursor.getString(columnIndex);cursor.close();callback(filePath);}}});
}

3. 编写上传文件的代码

结合uni.uploadFile方法来上传选择的文件:

<template><view class="container"><button @click="pickAndUpload">选择并上传文件</button></view>
</template><script>
export default {methods: {pickAndUpload() {pickFile((filePath) => {if (filePath) {this.uploadFile(filePath);} else {uni.showToast({title: '未选择文件',icon: 'none'});}});},uploadFile(filePath) {uni.uploadFile({url: 'https://your - server - url.com/api/upload', // 替换为实际的上传接口地址filePath: filePath,name: 'file',success: function (res) {console.log('文件上传成功', res.data);uni.showToast({title: '文件上传成功',icon:'success'});},fail: function (err) {console.log('文件上传失败', err);uni.showToast({title: '文件上传失败',icon: 'none'});}});}}
};
</script><style scoped>
.container {padding: 20px;
}
</style>

很详细~

然而只有一个问题:不work!

o(╯□╰)o

正确答案

最后还在uniapp的论坛上找到了答案,已经通过android app测试,可用~

使用原生的Native.js调用📱平台的文件管理器,选择文件并向上传文件的相关方法传递所选文件的正确路径。

如果会安卓原生编程,代码so easy。

// from DCloud
window.PickFile = function(callback,acceptType){  function ip(obj){  plus.android.importClass(obj);  return obj;  }  if(plus.os.name == 'Android' && typeof callback == 'function'){  var CODE_REQUEST = 1000;  var context = plus.android.runtimeMainActivity();  ip(context);  var Intent = plus.android.importClass('android.content.Intent');  var intent = new Intent(Intent.ACTION_GET_CONTENT);  intent.addCategory(Intent.CATEGORY_OPENABLE);  if(acceptType){  intent.setType(acceptType);  }else{  intent.setType("*/*");  }  context.onActivityResult = function(requestCode,resultCode,intentData){  if(requestCode == CODE_REQUEST){  if(intentData){  var uriValue = intentData.getData();  plus.android.importClass(uriValue);  var scheme = uriValue.getScheme();  if(scheme == 'content'){//还需要进行数据库查询,一般图片数据  var cursor = ip(context.getContentResolver()).query(uriValue,['_data'], null, null, null);  if(cursor){  ip(cursor).moveToFirst();  var columnIndex = cursor.getColumnIndex('_data');  picturePath = cursor.getString(columnIndex);  cursor.close();  callback(picturePath);//返回文件路径  }  }else if(scheme == 'file'){  callback(uriValue.getPath());//返回文件路径  }  }else{  callback(null);  }  }  }  context.startActivityForResult(intent,CODE_REQUEST);  }  
}

实现

为了h5还是先判断下环境

const BaseInfo = uni.getAppBaseInfo();

BaseInfo.uniPlatform==="app”的话用,h5还是uni.chooseFile

function ip(obj){  plus.android.importClass(obj);  return obj;  }
uploadFileInit(){const CODE_REQUEST = 500;  let context = plus.android.runtimeMainActivity();  ip(context);  let Intent = plus.android.importClass('android.content.Intent');  let intent = new Intent(Intent.ACTION_GET_CONTENT);  intent.addCategory(Intent.CATEGORY_OPENABLE);  intent.setType("*/*");   context.onActivityResult = function(requestCode,resultCode,intentData){  if(requestCode == CODE_REQUEST){  if(intentData){  var uriValue = intentData.getData();  plus.android.importClass(uriValue);  var scheme = uriValue.getScheme();  if(scheme == 'content'){//还需要进行数据库查询,一般图片数据  var cursor = ip(context.getContentResolver()).query(uriValue,['_data'], null, null, null);  if(cursor){  ip(cursor).moveToFirst();  var columnIndex = cursor.getColumnIndexOrThrow('_data');  try{var filePath = cursor.getString(columnIndex);  _this.filePath = filePath;cursor.close();//  _this.调用上传接口的方法(filePath, ‘文件类型’);}catch(e){}}  }else if(scheme == 'file'){  // 路径 uriValue.getPath()}  }else{  uni.showToast({title: '选择文件失败',icon: 'none'});}  }  }  context.startActivityForResult(intent,CODE_REQUEST);  
}

找了好久~真机测试可行~

吐槽

uniapp这个是个坑,明明很多文件选择插件,都不兼容~

官方会推荐兼容的插件——当然:收费~

其他实现方式推荐

曲线救国:web-view

在 web-view 组件内可以使用 input 元素进行选择,使用表单或者 xhr 上传;

在插件市场搜索:全文件上传选择非原生

全文件上传选择非原生2.0版 - DCloud 插件市场

http://www.lryc.cn/news/2404452.html

相关文章:

  • ASR技术(自动语音识别)深度解析
  • 图论水题2
  • Ctrl-Crash 助力交通安全:可控生成逼真车祸视频,防患于未然
  • 网络编程之服务器模型与UDP编程
  • Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型时序预测
  • 阿里云服务器安装nginx并配置前端资源路径(前后端部署到一台服务器并成功访问)
  • Ubuntu 下开机自动执行命令的方法
  • C++11新增重要标准(下)
  • 【第六篇】 SpringBoot的日志基础操作
  • Pluto论文阅读笔记
  • ubuntu显示器未知
  • Faiss向量数据库全面解析:从原理到实战
  • matlab 2024a ​工具箱Aerospsce Toolbox报错​
  • 使用有限计算实现视频生成模型的高效训练
  • Server2003 B-1 Windows操作系统渗透
  • 一次Oracle的非正常关闭
  • AI不会杀死创作,但会杀死平庸
  • JeecgBoot低代码管理平台
  • Fetch与Axios:区别、联系、优缺点及使用差异
  • YOLO11解决方案之分析
  • yolov11与双目测距结合,实现目标的识别和定位测距(onnx版本)
  • 基于51单片机和8X8点阵屏、独立按键的填充消除类小游戏
  • 将数据库表导出为C#实体对象
  • 物联网技术发展与应用研究分析
  • 金融系统渗透测试
  • C++ 信息学奥赛总复习题
  • 9.进程间通信
  • 性能剖析:在 ABP 框架中集成 MiniProfiler 实现性能可视化诊断
  • React 基础入门笔记
  • C++.OpenGL (12/64)光照贴图(Lightmaps)