背景分析:微信小程序不支持直接选择图片、视频之外的文件上传,可通过两种方式实现文件选择。
1、就使用官方提供的 wx.chooseMessageFile() 方法,但是该方式只能通过聊天记录选择文件(即用户须提前将所需文件发送至微信任意聊天记录中,否则也是无法选择的);
2、使用web-view嵌入html,html使用原生input选择文件上传即可。
具体实现代码核心显示如下:
法1:
temeplete
<uni-forms-item label="附件上传" name="tag_file" v-if="tag_status_index == 1 || tag_status_index == 2" @tap="selectFile">
<view class="notice">
<view class="notice" style="margin-bottom: 30rpx;">
<text>注:文件格式:zip、rar、doc、docx、pdf,且仅支持选择一个文件,文件大小不超过10M</text>
<text>步骤1:指定附件xx作品(若作品较多建议选择zip或者rar格式)。发送至微信【文件传输助手】</text>
<text>步骤2:点击【附件上传】- 选择聊天记录里面的【文件传输助手】</text>
<text>步骤3:选择xx作品后关闭聊天记录弹框后即可上传附件</text>
</view>
<view style="display: flex;">
<u--input placeholder="请选择附件(必填)" v-if="page_info.isEdit" v-model="resumeInfo_tag_file"
readonly border="bottom" placeholderStyle="color:#999;font-size:13px;" clearable>
</u--input>
<u--input placeholder="请选择附件(必填)" v-else v-model="resumeInfo_tag_file"
readonly border="bottom" placeholderStyle="color:#999;font-size:13px;" clearable>
</u--input>
<u-icon name="arrow-right" icon="#999" size="15"></u-icon>
</view>
</view>
</uni-forms-item>
script
data() {
return {
maxSize:10485760, // 文件最大限制 10M
}
}
/* 选择附件上传 */
selectFile(e){
/* uni.navigateTo({
url:"../webView/webView"
})
return false; */ 注释部分代码就是法2实现方式:跳转webview
let _this = this;
wx.chooseMessageFile({
count: 1,
type: 'file',
success (res) {
// tempFilePath可以作为img标签的src属性显示图片
const tempFilePaths = res.tempFiles;
console.log('tempFilePaths',tempFilePaths);
try {
res.tempFiles.map(val => {
// console.log('val',val);
if(val.size > _this.maxSize){
uni.showToast({
icon: 'none',
title: '上传的文件大小不超过10M'
});
throw new Error();
}else{
uni.uploadFile({
url: _this.$serverUrl + "/api?operate=normal.upload.single",
filePath: tempFilePaths[0].path,
name:'file',
formData: {
'file': tempFilePaths[0].path
},
success: (result) => {
let _result = JSON.parse(result.data);
// console.log('_result',_result);
uni.showLoading({
title:"正在上传..."
})
if (_result.code == 1) {
uni.showToast({
title: _result.msg,
icon: "none"
});
_this.signUpformData_info.tag_file = "";
_this.signUpformData_info.tag_file = _result.data.url;
_this.resumeInfo_tag_file = val.name;// 附件名称
uni.hideLoading();
} else {
uni.showToast({
title: '上传失败',
icon: "none"
});
}
},
fail: function(fail) {
console.log('fail',fail);
uni.showToast({
title: "上传失败",
icon: "none"
})
}
});
}
})
}catch(e){
console.log('选文件',e);
}
},
});
},
法2:
<template> <view> <web-view src="域名/?page=webView&key=info&isEdit=true" bindmessage="handleMessage"></web-view> <view>{{file}}</view> </view> </template> <script> export default { data(){ return { file:'' } }, methods: { handleMessage(evt) { console.log('接收到的消息:' + JSON.stringify(evt.detail.data)); } }, onLoad(option) { if(option.data){ console.log('option',JSON.parse(option.data)); let _data = JSON.parse(option.data); this.file = _data.origin_name; } } } </script>
注意:bindmessage 是小程序回退或者当前页面卸载销毁才会执行的回调,个人觉得这种方式是很不符合需求的(测试过程中没有一次拿到过该回调的内容),解决方案是直接在web-view页面内部返回时直接把参数以string方式带在路径上即可。
webview.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0,
maximum-scale=1.0,
user-scalable=0">
<title>附件选择</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="{$static_path}js/jquery.min.js"></script>
<script src="{$static_path}js/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
<style>
.upload-active{
margin: 100px auto;
text-align: center;
}
</style>
</head>
<body>
<div class="upload-active" id="upload">
<el-upload
name="file"
:limit="1"
accept=".docx"
action="/api?operate=normal.upload.single"
ref="uploadref"
:auto-upload="true"
:show-file-list="true"
:before-upload="beforeUpload"
:on-success="handleSuccess"
:on-error="handleError"
:before-remove="beforeRemove"
:on-remove="handelRemove"
:data="type" >
<el-button type="warning" size="medium"> 选择文件</el-button>
<div slot="tip" class="el-upload__tip">可上传doc/docx/pdf/zip/rar等文件</div>
</el-upload>
</div>
<script>
new Vue({
el:"#upload",
data:{
type:{
type:0
},
isDisabled:false
},
created(){
this.init();
},
methods:{
beforeUpload(){},
handleSuccess(res){
console.log('上传成功',res);
if(res.code == 1){
wx.miniProgram.postMessage({
data: {
upload: res.data
}
});
setTimeout(function () {
wx.miniProgram.navigateTo({
url:"../resumeDetail/resumeDetail?data="+JSON.stringify(res.data)+'&key=info&isEdit=true'
});
},2000);
}
},
handleError(){},
beforeRemove(){},
handelRemove(){
this.$refs.uploadref.clearFiles();
},
init(){
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0,
maximum-scale=1.0,
user-scalable=0">
<title>附件选择</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="{$static_path}js/jquery.min.js"></script>
<script src="{$static_path}js/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
<style>
.upload-active{
margin: 100px auto;
text-align: center;
}
</style>
</head>
<body>
<div class="upload-active" id="upload">
<el-upload
name="file"
:limit="1"
accept=".docx"
action="/api?operate=normal.upload.single"
ref="uploadref"
:auto-upload="true"
:show-file-list="true"
:before-upload="beforeUpload"
:on-success="handleSuccess"
:on-error="handleError"
:before-remove="beforeRemove"
:on-remove="handelRemove"
:data="type" >
<el-button type="warning" size="medium"> 选择文件</el-button>
<div slot="tip" class="el-upload__tip">可上传doc/docx/pdf/zip/rar等文件</div>
</el-upload>
</div>
<script>
new Vue({
el:"#upload",
data:{
type:{
type:0
},
isDisabled:false
},
created(){
this.init();
},
methods:{
beforeUpload(){},
handleSuccess(res){
console.log('上传成功',res);
if(res.code == 1){
wx.miniProgram.postMessage({
data: {
upload: res.data
}
});
setTimeout(function () {
wx.miniProgram.navigateTo({
url:"../resumeDetail/resumeDetail?data="+JSON.stringify(res.data)+'&key=info&isEdit=true' // 上传结果直接带在路径里面
});
},2000);
}
},
handleError(){},
beforeRemove(){},
handelRemove(){
this.$refs.uploadref.clearFiles();
},
init(){
}
}
})
</script>
</body>
</html>
resumeDetail.vue接收参数(onload周期)
onLoad(option) {
if(option.data){
console.log('option',JSON.parse(option.data)); // 跳转页面上传文件
}
}