uni-app 使用webview上传文件:自有服务器版本
简介
因为小程序和uni-app框架对于文件上传的限制,所以在实际开发中,官方提供的api无法满足我们的上传需求,所以需用通过webview来实现对特定文件的上传
本文介绍的方式是在webview链接的网页里直接通过axios上传到自有服务器中,再把后端返回的链接传递给小程序或者app
因为本项目是一个多语言的项目,所以代码里会有对多语言的处理
webview链接的页面
项目结构
代码介绍
上传进度:可以通过axios的onUploadProgress 来获取上传进度
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">
<div id="info">请选择音视频文件</div>
<div id="limitInfo">(文件后缀为.mp3,文件大小不能超过10M)</div>
</div>
<div
style="
font-size: 14px;
text-align: center;
color: #999;
padding-top: 10px;
"
>
<span id="progressText">上传进度:</span>
<span id="percent">未选择文件上传</span>
</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/language.js"></script>
<!-- <script type="text/javascript" src="./utils/qiniu.min.js"></script> -->
<script type="text/javascript">
let maxSize = 5 * 1024 * 1024;
window.onload = () => {
var uploadDOM = document.getElementById("upload");
uploadDOM.style.display = "block";
var token = getUrlParam("token");
var language = getUrlParam("language");
const languageText = language == "en" ? EnglishText : ChineseText;
// alert(`accessToken:${accessToken},doamin:${domain}`);
let percentDom = document.getElementById("percent");
percentDom.innerText = languageText.p_info;
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">${languageText.noSelect}</div>`;
var btn = document.getElementById("btn");
btn.innerText = languageText.btnText;
var info = document.getElementById("info");
info.innerText = languageText.info;
var limitInfo = document.getElementById("limitInfo");
limitInfo.innerText = languageText.limitInfo;
var progressText = document.getElementById("progressText");
progressText.innerText = languageText.progressText;
// 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">${languageText.sizeError}</div>`;
alert(languageText.sizeInfo);
return;
}
let size = (file.size / 1024 / 1024).toFixed(2);
let name = file.name;
let type = fileType(file.name);
if (type != "mp3") {
box.innerHTML = `<div class="error">${languageText.typeError}</div>`;
alert(languageText.typeInfo);
return;
}
box.innerHTML = `<div>
<div>${languageText.name}:${name}</div>
<div>${languageText.size}:${size}M</div>
</div> `;
let formData = new FormData(); //声明一个formdata对象,用于存储file文件以及其他需要传递给服务器的参数
formData.append("file", file);
axios({
url: `/api/file/upload?mime=image&source=message&lang=${
language == "en" ? "en-us" : "zh-cn"
}`,
method: "post",
headers: {
Authorization: token,
"Content-Type": "multipart/form-data",
},
data: formData,
onUploadProgress: (progressEvent) => {
//原生获取上传进度的事件
if (progressEvent.lengthComputable) {
//属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量
//如果lengthComputable为false,就获取不到progressEvent.total和progressEvent.loaded
let percent = (
(progressEvent.loaded / progressEvent.total) *
100
).toFixed(0); //实时获取上传进度
percentDom.innerHTML = percent + "%";
}
},
})
.then((res) => {
console.log("上传结束", res, res.data.data.src);
// result.url = domain + "/" + result.key;
// result.type = type;
// result.name = name;
if (res.data.code == 200) {
// 接收成功后返回的信息
uni.postMessage({
data: {
action: JSON.stringify({
src: res.data.data.src,
}),
},
});
setTimeout(() => {
uni.navigateBack();
}, 500);
} else {
alert(res.data.msg);
}
})
.catch(() => {
box.innerHTML = `<div class="error">${languageText.errorInfo}</div>`;
});
};
};
// 获取小程序传递过来的参数
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);
return ext;
// //判断是否是视频类型
// 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"
export default {
data() {
return {
url: "http://a1003-upload.demo.huizhouyiren.com"
}
},
onLoad(options) {
let lang = uni.getStorageSync("languageKey") ? (uni.getStorageSync("languageKey") == 'en' ? 'en' :
'zh-cn') : 'en-us'
let token = uni.getStorageSync("token")
this.url = `${this.url}?language=${lang}&token=${token}`
},
methods: {
handleMessage(evt) {
uni.setStorageSync('uploadFile', JSON.parse(evt.detail.data[0].action))
},
}
}
</script>
<style>
</style>