由于uni框架的限制,只能选择图片进行上传,那如果想要选择文件上传呢?
使用renderjs
uniapp中不能像h5那样获取操作生成DOM,在开发中就会碰到很多需要绕很多弯路才能解决的问题,但uniapp提供了renderjs来弥补这个缺陷
基本使用
<template>
<button type="primary" size="mini" @tap="yourModule.onClick">选择文件</button>
</template>
// 注意,一定要使用选项式API
<script>
export default {
data(){
return{
}
},
methods:{
}
}
</script>
<script module="yourModule" lang="renderjs">
export default {
data(){
return{
}
},
methods:{
onClick(){
console.log('触发了yourModule的onClick方法')
}
}
}
</script>
更多renderjs的使用方法请参考:renderjs使用方法
实现思路:
相信你已经基本熟悉了renderjs的使用方法,接下来介绍选择文件的具体思路
使用renderjs创建一个type为file的input标签,使用click方法触发选择,就可以选择文件,再监听input的onchange事件,获取到选择的文件File对象,再将其转成base64回发给数据层,在数据层使用plus的api将base64转成本地路径,有了本地路径是不是就好办多了?使用uni.uploadFile就能实现上传。话不多说直接上代码
<template>
<button type="primary" size="mini" @tap="attchChoose.onClick">选择文件</button>
</template>
<script>
import {
API_SITE
} from '@/config/config'
import pop from '@/util/pop'
import {
uploadFile
} from '@/common/request.js'
export default {
data() {
return {
}
},
methods: {
async upload(path) {
try {
// pop.showLoading()
// 参数一:本地路径,参数二:后端对应字段名,我这里只是进行了简单的封装
const result = await uploadFile(path,"files");
console.log(result);
// pop.showToast("上传成功")
} catch (e) {
console.log(e);
// pop.showToast(e)
}
},
async chooseFile(data) {
try {
const fileUrl = await this.base64toPath(data.base64Str, data.attachName);
this.upload(fileUrl.localAbsolutePath)
} catch (e) {
console.log("err", e);
}
},
/**
* @param {Object} base64 文件base64
* @param {Object} attachName //文件名需要后缀,如:张三.jpg
*/
async base64toPath(base64, attachName) {
let _that = this;
return new Promise(function(resolve, reject) {
const filePath = `_doc/yourFilePath/${attachName}`;
plus.io.resolveLocalFileSystemURL('_doc', function(entry) {
entry.getDirectory("yourFilePath", {
create: true,
exclusive: false,
}, function(entry) {
entry.getFile(attachName, {
create: true,
exclusive: false,
}, function(entry) {
entry.createWriter(function(writer) {
writer.onwrite = function(res) {
const obj = {
relativePath: filePath,
localAbsolutePath: plus.io
.convertLocalFileSystemURL(
filePath)
}
resolve(obj);
}
writer.onerror = reject;
writer.seek(0);
writer.writeAsBinary(_that
.getSymbolAfterString(base64,
','));
}, reject)
}, reject)
}, reject)
}, reject)
})
},
// 取某个符号后面的字符
getSymbolAfterString(val, symbolStr) {
if (val == undefined || val == null || val == "") {
return "";
}
val = val.toString();
const index = val.indexOf(symbolStr);
if (index != -1) {
val = val.substring(index + 1, val.length);
return val;
} else {
return val
}
}
}
}
</script>
<script module="attchChoose" lang="renderjs">
let fileInputDom = null;
export default {
methods: {
createFileInputDom() {
fileInputDom = document.createElement("input");
fileInputDom.setAttribute('type', 'file');
fileInputDom.setAttribute('accept', '*');
},
onClick(event, ownerInstance) {
if (!fileInputDom) {
this.createFileInputDom();
}
fileInputDom.click(); // 模拟click
fileInputDom.addEventListener('change', (e) => {
fileInputDom = null;
let choicesFiles = e.target.files[0];
let reader = new FileReader();
//读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
reader.readAsDataURL(choicesFiles);
reader.onload = function(event) {
const base64Str = event.target.result; // 文件的base64
ownerInstance.callMethod('chooseFile', {
attachName: choicesFiles.name,
size: choicesFiles.size,
base64Str,
})
}
e.target.value = "";
})
}
}
}
</script>
亲测有效