uni-app 使用webview上传文件:七牛云版本
简介
因为小程序和uni-app框架对于文件上传的限制,所以在实际开发中,官方提供的api无法满足我们的上传需求,所以需用通过webview来实现对特定文件的上传
本文介绍的方式是在webview链接的网页里直接通过七牛的JSSDK直接将文件上传的七牛云中,然后把获取的key和hash值传递会小程序或者app中
因为uni-app框架的限制,导致在下载文件的时候存储的路径用户难以寻找,所以本文展示的代码里也会包含文件下载功能
webview链接的页面
项目结构
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
</head>
<body>
<div class="box">
<div class="upload" id="upload">
<input type="file" id="f" />
<div class="file_info">
<div class="file_box" id="file_box">
<!-- <div class="error">未选择文件</div> -->
<!-- <div class="error">文件大小超过限制</div> -->
<!-- <div class="error">文件类型错误</div> -->
<!-- <div>
<div>文件名:jkdaljsfklaj.mp3</div>
<div>文件大小:1M</div>
</div> -->
</div>
</div>
<div class="btn_box">
<div class="btn" id="btn">选择文件</div>
</div>
<div class="mes">(文件大小不能超过5M)</div>
<div
style="
font-size: 14px;
text-align: center;
color: #999;
padding-top: 10px;
"
>
<span>上传进度:</span>
<span id="percent">未选择文件上传</span>
</div>
</div>
<div class="download" id="download">
<div style="display: flex; justify-content: center">
<img
src="/images/logo.png"
alt=""
style="width: 80px; height: 80px"
/>
</div>
<div
style="
font-size: 15px;
color: #2dc4b5;
text-align: center;
margin: 10px 0px;
"
>
英才云
</div>
<div
style="
text-align: center;
font-size: 16px;
margin-top: 20px;
font-weight: bold;
color: rgb(102, 102, 102);
"
>
互联网灵活用工云平台
</div>
<div
style="
text-align: center;
font-size: 12px;
margin-top: 20px;
color: rgb(154, 154, 154);
"
>
(点击下载后,请自行返回聊天页面)
</div>
</div>
</div>
</body>
</html>
<script type="text/javascript" src="./utils/jweixin.js"></script>
<script type="text/javascript" src="./utils/uni-webview.js"></script>
<script type="text/javascript" src="./utils/axios.js"></script>
<script type="text/javascript" src="./utils/qiniu.min.js"></script>
<script type="text/javascript">
let maxSize = 5 * 1024 * 1024;
window.onload = () => {
var downloadUrl = decodeURI(getUrlParam("downloadUrl"));
var uploadDOM = document.getElementById("upload");
var downloadDOM = document.getElementById("download");
if (downloadUrl && downloadUrl != "null") {
uploadDOM.style.display = "none";
downloadDOM.style.display = "block";
download(downloadUrl);
return;
}
uploadDOM.style.display = "block";
downloadDOM.style.display = "none";
var accessToken = getUrlParam("accessToken");
var domain = getUrlParam("domain");
let percentDom = document.getElementById("percent");
document.addEventListener("UniAppJSBridgeReady", function () {
// console.log("uni准备就绪");
// alert("uni准备就绪");
// uni.postMessage({
// data: {
// action: 'postMessage'
// }
// });
});
// 添加节点
var box = document.getElementById("file_box");
box.innerHTML = '<div class="error">未选择文件</div>';
// input节点
var f = document.getElementById("f");
// 监听按钮点击
var btn = document.getElementById("btn");
btn.addEventListener("click", () => {
f.click();
});
f.onchange = () => {
let file = f.files[0];
console.log(f.files[0]);
if (file.size > maxSize) {
box.innerHTML = '<div class="error">文件大小超过限制</div>';
alert("不能上传大于5M的文件");
return;
}
let size = (file.size / 1024 / 1024).toFixed(2);
let name = file.name;
let type = fileType(file.name);
console.log("type", type);
box.innerHTML = `<div>
<div>文件名:${name}</div>
<div>文件大小:${size}M</div>
</div> `;
let observable = qiniu.upload(file, name, accessToken);
var subscription = observable.subscribe({
// 上传开始
next: (result) => {
// 接收上传进度信息,result是带有total字段的 Object
// loaded: 已上传大小; size: 上传总信息; percent: 当前上传进度
console.log(result); // 形如:{total: {loaded: 1671168, size: 2249260, percent: 74.29856930723882}}
let percent = result.total.percent.toFixed(0);
percentDom.innerHTML = percent;
},
error: (errResult) => {
box.innerHTML = '<div class="error">文件上传失败,请稍后再试</div>';
// 上传错误后失败报错
// console.log(errResult);
},
complete: (result) => {
result.url = domain + "/" + result.key;
result.type = type;
result.name = name;
// 接收成功后返回的信息
// console.log(result); // 形如:{hash: "Fp5_DtYW4gHiPEBiXIjVsZ1TtmPc", key: "%TStC006TEyVY5lLIBt7Eg.jpg"}
// alert(`上传成功: ${JSON.stringify(result)}`);
uni.postMessage({
data: {
action: JSON.stringify(result),
},
});
setTimeout(() => {
uni.navigateBack();
}, 500);
},
});
};
};
// 获取小程序传递过来的参数
function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
// 判断文件类型
function fileType(filePath) {
//获取最后一个.的位置
var index = filePath.lastIndexOf(".");
//获取后缀
var ext = filePath.substr(index + 1);
//判断是否是视频类型
if (
["mp4", "avi", "mov", "rmvb", "rm", "flv", "3gp"].indexOf(
ext.toLowerCase()
) != -1
) {
return "video";
}
//判断是否是图片类型
if (
[
"png",
"jpg",
"jpeg",
"bmp",
"gif",
"webp",
"psd",
"svg",
"tiff",
].indexOf(ext.toLowerCase()) != -1
) {
return "image";
}
//判断是否是音频类型
if (
["cda", "wav", "mp3", "wmv", "flac", "aac"].indexOf(ext.toLowerCase()) !=
-1
) {
return "audio";
}
if (
["doc", "xls", "ppt", "pdf", "docx", "xlsx", "pptx"].indexOf(
ext.toLowerCase()
) != -1
) {
return "document";
}
return "otherType";
}
// 下载文件
function download(downloadUrl) {
let link = document.createElement("a"); // 创建a标签
link.style.display = "none";
link.href = downloadUrl + "?response-content-type=application/octet-stream"; // 设置下载地址
link.setAttribute("download", ""); // 添加downLoad属性
document.body.appendChild(link);
link.click();
}
</script>
uni-app项目中的webview 页面
代码功能介绍
1、参数传递:在该页面中,需要传递webview链接的网页中所需要的参数:七牛云授权token,七牛云的上传地址,以及页面类型(是上传文件还是下载文件,下载文件时还需要传递要下载文件的链接地址)
2、数据处理:在该页面中需要处理webview链接页面传递回来的数据,通过@message="handleMessage" 绑定处理函数 ,在绑定的函数中可以获取到传递回来的数据,是字符串形式的
javascript
<template>
<web-view :src="url" @message="handleMessage"></web-view>
</template>
<script>
import {
mapState
} from "vuex"
import {
uploadUrl
} from "@/common/constant.js"
export default {
data() {
return {
url: ""
}
},
computed: {
...mapState('thirdParty', ['qiniuData'])
},
onLoad(options) {
this.url = uploadUrl
if (options.downloadUrl) {
let url = `${this.url}?downloadUrl=${options.downloadUrl}`
this.url = encodeURI(encodeURI(url))
} else {
this.url = `${this.url}?accessToken=${this.qiniuData.accessToken}&domain=${this.qiniuData.domain}`
}
},
methods: {
handleMessage(evt) {
console.log('接收到的消息:' + JSON.stringify(evt.detail.data));
uni.setStorageSync('uploadFile', evt.detail.data)
},
}
}
</script>
<style>
</style>