Skip to content
On this page

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>