uniapp微信小程序PC端选择文件(无法使用wx.chooseMessageFile问题)

客户要求通过小程序选择excel文件并读取数据导入,查了一下资料,微信小程序选择文件是调用API【wx.chooseMessageFile】,知道了之后马上开干,没一会做好了,却发现在电脑端微信小程序上面调用此API没有反应,一看就是不支持PC端,怎么办,用户一般都是电脑填好excel,然后导入的。要让用户填好,然后发给好友,再去手机端操作?估计被喷死。查了度娘,看到了有说写一个HTML文件,用【webview】打开,实现上传,了解了一下,开干!!


注意:webview组件账户主体类型为个人的,无法使用!!关闭这个文章的页面吧。


先上html页面效果图


步骤:用户点击上传按钮,判断是否手机端,如果是,则正常走wx.chooseMessageFile ,如果是电脑端,则进入webview打开我们写的html页面,页面使用原生input类型是file。选择文件后,将文件解析成base64并返回至小程序(也可以直接上传至后端,由于我的逻辑代码都是写在了小程序里面,所以把base64返回小程序再上传)。


1:创建一个HTML文件

复制代码创建一个text文件写入,改后缀名为html。代码如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  </head>
  <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
  <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script> 
  <body>
    <div class="panel">
      <input type="file" onChange="onFileChange()" id="fileUpload" />
      <div class="upload-view" onClick="onUploadClick()">
        <img class="upload-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAHX5JREFUeF7tXQuYFMW1/k/vgkbhxviC6dlESRSNRmM0ik8iQfFx0cTHmk98RBMVEwHdmQHU5Jr1eiXCTs9yQUwwV40mxkTU+Irgm/hATWI0KMagEY07PRDfgaDAbp+7NQzv2d3uquqZnp6q7+MDvq3/1Dl/9b9d3V11DsE0w4BhoEcGyHBjGDAM9MyAEYi5OgwDvTBgBGIuD8OAEYi5BgwDcgyYO4gcbwZVJwwYgdTJRJsw5RgwApHjzaDqhAEjkDqZaBOmHANGIHK8GVSdMGAEUicTbcKUY8AIRI43g6oTBoxA6mSiTZhyDBiByPFmUHXCgBFIhSeaW/fqj099OASN1ATwtmBsW/wb4u/iH9H+vfYP/RtU+ruTO/Dxdkuo9ZXVFXa5roczAglp+rl1pwHYpt+hIBwKi4cANASEIWA0KQ1J6ABjCcBL4NESMBZg5ZoF1PrOCiW7BlyWASMQTRcGO/ZnwXwkgEMBEsLYV5Npf2YYCwFeAGABGvo/Qi1vFfwBTa/eGDACkbw+ikulT390NBhHw/NGguhLkqbCgj0PD/ejkZ7ANoOfpLHPrwlroDjbNQIJOLvsJEcCPAbAaAA7B4RXq7sLYC4a+Ba6pPBEtZyoxXGNQHzMGs/YbSt0rhSiGAPGUT4gUe5yL8C3ULpwZ5SdjIpvRiC9zATPGLwTVlkXwcLpAIZGZdK0+MF4BuCfU6ZwvRZ7MTViBFJmYrlt0LZoaPg+GN8HsGtM535dWM+D+XojlPKzbASyGS+cs9cJY++YC2Pz8IxQyky4EUiJFHaSowGeDODwOhPG5uE+BdBUSufvr3MeiuHXvUC4bdAQWNZkgMaaC2JjBng2PG8qTVy2pJ55qWuBcNYeD4K4ayTr+SLoJfY8GFMp486sV37qUiDcjAYckrgWTBfW68QHipv4p3imMI7moCsQLgad604gPO2zX0BD17UAjo3B/FUyhHnoahhHk97+eyUHrfZYdSUQbk9+HR7PArBntYkvjf8xALHJcAUIy8FYAQaBeABAA8EYCGAgCP0j4u+rsOgiask/FhF/QnejbgTCbfYYWLgBwNahs7r5AISFYFoIwt+6v8YvRicWYyUvplZ3pR9f+NrkDliDofCwR+mD5VCA9wcwxA9ec59PQBhHKVdwGftWFwLhbOI8EP2sgrO5qHsJ9yxAT8FqfDCsnbWlN3CHgXAYPBxe0Q2TRFMolf9BBTmtylCxFwg7tnhLdU3o7BI/B6a58Kx5NLHjudDHKzMAtzUNA7zj0MDHdvsyLHQfGL+mjCu24cS2xVognEvMAdOpIc6eCw8/A6y51RJFT7GtF4uF8wHYIXLwEKXdY0K0X1XTsRUI5xKPg0kcYAqjrRVGY7/ZYS2fdDnN7bsk0LlmLEIVCs+hdOE0XT5HyU4sBcKOfQ+AE0Mg+n14mFkLwtg89o2EMh7A9iFwM5XS7qUh2K2qydgJhB1bPIyfFwKrt4K9KZRZ+koItitmkrOD9wJZlwM4Q/ugHq6kiW6rdrtVNBgrgXAueTWYxeTrbIvA/GPKFG7VabTatjibOANElwHQu2s5ZiKJjUA4m/w2iH+u+cKbAbKupFTH+5rtRsIc55q2B7yrSude9PnEdA5l8jfrM1g9S7EQCE9NfBUNNA+EHbRQWfygR1dQKn+7FnsRN1L8TmTRNWBN/DHeQxcfS5MLf4p46H26V/MC4dZdt8aA1Q+CMLzPaP11uBFkXUGpjry/7vHoxe2J/dFFU0GaztwznsCK/sdQ65uf1DJDtS+QrD0LVDwaq96YMpTJO+qGatcC55K3gPksLREwrqOMe5EWW1UyUtMCYSd5DsA3aeGOMYYy7m1abNW4Ec4mfgLSdRSAzqV0XvezYcUYrlmBcPvgXeFZj2tJquB5I2ji0vkVY70GBuJcsgXMOQ2uvgnLG0EtS9/UYKviJmpXII4t7hznKDPGGEUZ92FlOzE0UDoe8KiG0H5OafdcDXYqbqImBaJtaUUYTylXHJ4yrQcG2Ek2A6zhbV5tLrVqTiDFJNGASJ+plq8qZh+0wlQ455I/BPNVimO8CbIOr7W3gzUokGQ7wJcoTZYRR2D62En+AuAzAwM3BjBNoUxtnSGpKYFw1j4chCeVJgl0J6XzYW6BV3MvomievvMgdDY+pFjW4UM0WgfRxR2vRTTMLdyqLYE49l0ATlIgdynYG1nrGw4V4leC8jR7VHc+mAeVjICmUzrfomajcuiaEUhpc90v1ajhCyhdqOTRWzV3I4hmx850l4prU3BtDbroIJqUf1HBRsWgtSMQJ/kHgA+UZoZwM6Vc9dfC0g7EB6j8tZ35p5QpfK8WGKkJgbDTdDzg/U6B0KUg6whKdbyuYMNASwxwrmm37qWqeBYcLEnKSpD15VqYjxoRiOJHQcaEek6fKXkR9worpW2doWD7Kkq7VyjgKwKNvEBKW0pe3qhEcjBiiOZSKn98MJDp7YcBziUfAPNxfvqW6fMWrP77UcubH0riKwKLvkBy9kQwpkmzQTycUgXFV8PSo8cayLnEEWCSr3lYA3f2GhBI4lmFHE+zKO2Oi/VVWuXgOGvfCILcPivi5yhVOLjKIfQ6fKQFUsztZHnPShK4AuwNM988JNnzCVO+i3jWwVHLKbZx6BEXiN0KCz/yOVebd4tlGhpJLkKFsZO4HaBmqUEivu0n2gLJSS+vlmINhtGl7j+kJs2AAjHA2cHHgawHAoHWdY74MiuyAlFcXplnD6mrVR7Eji1ehMjVd4zwMivCAlFaXn2D0u698tNtkEEZUNqCEuFlVnQF4tji9eERQScKgAuydqNUhyhOY1qFGOBpTbujwfsrgIbAQzJ+Rxl3dGBcBQCRFAhPtfdAI70EcD8JDmr2eKdErJGCcC55J5hPlnBqGTpX706T310ugQ0VEk2BOMnvAXydVOSEMyjl/koKa0BKDHB78ix4fIuUkYgmzoioQBT2Xln97KiXJJC6gGoAxDOSTVjDb0u5GtGcZJETCE9v2hdd3q8BfDEw0cTzKVUYERhnANoY4Jy9AIxDJAzeBubLKFN4SwIbGiQSAuEpg3dCfxoFwiiARLWiQVIRR/htiFQ8NQjibCIHIskTg/QGwI93p5F9DGtW3xeFZ5KqCoSd5AjAGw2iE8DYXfl6iOg6VjmuGjLA2cQxIJqnweVXwXgMFu6hlPuQBntSJiouEL7uc5/Bx50TAJwA4AApr3sAUdqteDw6/Y+LLXZs1hoL40Uw7sFWn+Rowvv/0mq7D2MVvaDYsUUiYyGOoSEEuZjSrqgjblqVGWDHFvXgw5jjRSC0V7JGe0UEwrnkaQBPAOOw0OaOcB+l3DDqEobmclwNc86+F1xcIYTVHgRzO2UKihlW+nYvVIGsfcbgiwF8o29XFHsQHEq5IuOGaVVmgHN2Fox0Bdy4AezlwjzSEIpAuG3QtrAapodUTLM878xjKVO4vgKTYobogwHOJi4A0ewKEfUveGgPq3iodoGUzpD/H4CRFSJo7TDmDVZF6e5tMG4bfCSsYmmKCjaegwH2GTT2+TU6B9UqEM4OPhCw7gKhSaeTvmyxdxBllv7RV1/TKVQGiuXcPHo+1EHKG1+ELjpTZ1I6bQLRkLtKjU/29g5zLarmXH2hOWvvCYLY2VudpnE/nhaBaKxGJE9oA3ahS8wJQnkC9SFLJSqqe5pTUyZ5ZYEonUfWNyfAVrQjjcu/p9OksSXHAE9J7oCt+F05tFbU3ZR2VZKdQ0kg7NhiS4HYO1WttgqMDhCWYfv+I+nc2i45XC0SdY9bKs39GAgJMGwQ+usew789nkPpwmn++2/aU1ogrF6KIIjPogDk/cV1bVEQ1lJQ5z/BjcvMycEgNFa+L8+2t8FHDQlYXQk00GB0cQJU3HcnMjLuViGPpDPcSAmEHVuUEDgv1OCI56OLfl/crJZ2Xwh1LGO8KgxwdvBeIOsoEB2rkMLUn++S9SgDC4RzyavBfLk/rwL2IpoLxu0AP0ppV+7gTcAhTfdoMMDtuySAzqPAOD08sQSvDxNIIJxNXAwi8YVcd3sWhJnmqKxuWmvTHufsMWCMB6A/LalFZ1NL/hd+mfEtEM7ap4Og+6z3qwCupbQ7y6/Dpl/9MFDa/S1yK++pNWqib1Eq76u0tS+BlLaPiK0DaqWX10VJWAmmKViz8lq69IOPtAZvjMWKAb7mM59Gv23GgfkKjW/DXofVb7if3AX+BOIoJFHYcrpegIXx1OI+HauZNMGEykD3WfdRYIgNkHp+Sa9duYhlXK+tT4GwkzwH4Jv6MuTr54xfY+DWF9LYN8xdwxdhptPGDPC0nQbD6if2+skkhdiSTItGU0u+19J+vQpE89KqtftI7JVmyg0Dqgywk7wD4FNU7YDxDFa4w6kVnT3Z6l0gupZWhNMp5YpUPqYZBrQwUHqAv1bZGOFHlHL/O7BAtC2tmJopk79DORBjwDCwGQPs2OKI9T2KxKwCecMptfQP5eyUvYPw9J0HoatRVHZSeyBitFHGnaQYgIEbBnpkgLP2JBCmKlIkdmt8079AnGQKYEdpUMLtlHK/pWTDgA0DPhjo3l5/A4Dv+OjacxfGKMq4D2/eofwdxLH/pJiz6mFKu6OUHDZgw4BPBrgVjRhozweUsub8itLuGX0KhNuSp8Hi3/j0rVy3P2F14yi67B8fKNioKyi3JQ8BeSNgUTMY+xWDJ7wIj+egAfOopfDnuiJEIlhuT+4Hj8UdYEcJ+FpImUpXW9xBOGffDZZO09MJi4eZCfU/RZyzHwSLnMQ9ttUAZqCT/pcm5zv8W66/npxNnAcisdNcsvFsShcu3Bi8iUDYsQ8FIP+Fm7idUoWUpHd1B+NgVbQWweJmailU76x3DcwQO8n53Qmwvybp6ipY/JWNOd5cIOK9skgPKtPegdc1jCYuWyIDrjcMZxPPgmhYsLj5JXRSM012RWpP08owwNnkqSCeI03OZm9e1wuEr7E/h374C4Dt5IzTFZTOXyWHrS9U9/t78UzxFcmo/4Iuq5kmdbwmiY89jB37bulsnoR3sIb2X7ec3SAQxxavycTrMpm2GKsbDzYP5n1Tx479MoC9++7Za48X0NXQTJPe/ruinVjC2UmOBPgR6eCYz6dMQSQ/3JC0gXPJ2WC+QMooYwJl3JlS2DoCcdZeXDqPrSPq5+F1NZslbXkqWWWbFOEmSrnF7yob30Ekf7PRG5TOf0HHjMfVBs9GP6ywxZJoF70x0h/RwKeafGBbssptTcNgeWI3iExbX0qjKBDONe0G9uTWtETXUyo/VsaLesDw1B0HorG/eKhOhBIv83Pob51KE8wr4M35ZZUP3p28F00u/HWtQLKJM0D0S7kJpNMonZd/ayA3aE2girUXt7ZEqqIdQnVYbNvequFUGv+2G+o4NWZcKcGIxWOppXD9WoE4tigbcL5U/KsbtzcP52Vu8Y79WQCLAAyU4jU46Cl0rWmmSe8sDQ6NJ4Jzgw8CW89JRncrpd0z1wnkdQDBnyOI5lIqf7ykA7GF8bSm3dHgvQRgqwoH+UTpwf2fFR43ssMpvDV8i9LursTZxC4gEpkLgzfz9moLzjjXtA/g/QWsltY1+GSUECLhnifO4LhRyI0rHYYuIDuJ/wHoB1L2vK7PE7cl/xMW3y9lgKzdKdUh7j6mFZ/lBh8IssoevKkoQaLOOKxmSnW8X9FxIzgYtw36EqwGcTcP3jwaTZyzzwXjxuBoLKe0+x8SuFhCOJc4AkxPRCY4xiNo6N9MLW9+GBmfquQIO7YoHR38WZDwHeKsfSkIP5bw3ZRdLpHGWftoEKpW7L6XuXsI/T5prnRtcYlrKVSIdFlqxmXEuWQOzC2BPSSeT6nCiMC4mAE4Z58Axr0RDmsetl7TTBe9syLCPobqGucSj4PpyMCDELUTO/atAMYEBgO3UdqVwUkMFU0IO8lmgH2lsKxuBPwABlAzjXVXVteP6ozOji1S5p4uMfqvxDPIw2AcFRhc53XJuT15Fjy+JTBv1QPcj+X9m6m1/ooMSddtJzxC7CQWArRP4HljylAmr5bYIfCg0QCwkzgfoFqsyX4vlm/XTK2viFOKddM4m0yDOBs8YH5J3EGWgjEoMJgxhjLubYFxNQ7grD0ehBk1HMbdWO4295ZNsIZjK+u6dGUCwjLxDMJShHjeCJq4VGSSqJvGOXsiGNNqPmCmu7AiL0Ti1XwsPgLgtsFHwrJEdYLATQhE9h3xGfVU8Iad5H8B3GOKysDMVxvAfAdlCs3VdqMS45cK8oiXUUHbciGQPAA7KBIeJtFEty0wrgYBEf7OocgmX03pwg8VjUQezm32RFhSd35XCEScVRgaPEqaTul88O8nwQeqOqI724v4CHi0RkfE2f8vB7Yn9lnJvM/vdSA6gdJ5ua1GgQOoDoCdZDvAl0iMvlgIRC6LYp2kFlU7K1N2Sp6Ch0dh4UeBJ6y4ERFvg+iswNieAIxnKOOKdE+xbZyzfwOGTK3050n6KyPwNKXdw2PLaikwdmxxkGyLlJRScYsqvtQ5Dp0NZ8sKROxeUNqhurnjjNVYsd3AOL/6Zcd+SiotqdgtopCsYQml3c9LXSg1BGLHfq87s+H2yi6L8taW9T2xw5bb7FYVgQhfuD1xATwSJcnUG/GBlCqIlUQsGzv2GwCGBA5OHCeX/4iCVZR2tw48aI0BOGsv0FDy6wak3POJUHylrkMgRTt66mMIU5+Lc116duxPpA6viY/h7CRHA3yf1HVbJtmvlJ0Ig6Qv5vUxbfkyQ9pmmQ2inE0MB5EoIiOZ8A8upd1khKdAyTVuT34dHj8qZ4ROEAIZCrBcKksPV9JEt1Vu8NpAcTZxDIjmSXnbQ3kvnQIp3knWnmL8JRj7Svh5N6XdkyRwNQFRyrcA2mPdmXS5r+nEz1GqcHBNMKXgpNRu0F6OI+sWSGm5JZJEiGrEIwOE+iG8rj1o4rLYnmGX/s4nksalXVonEPEb8pgAxG7oanV9gVqWiYegWLcAW3L+BfBFlC70mEYpDIEURTJrpwFY1XgTmE71NRmxfzhXeHwoLWdLieOSLWDO+SJ1807MYylTqMWdrYHD9XFhPwjiH/b1RsiHnfK++Tykxtnk1SC+vJcA7wZZ3437mXXOJX4Cpk3qffie9NLjw1qBiApHFi/wDd6kI8+hdEHmI4zccFVGFT8cWtYx8PjLoOKafxHAr8CjV/w+j4UtkLVLrsSZAI0EaO/uQ117ARD5shbCw0K/flaZauXhpV/vipFLm3E35ObN2m+D0CTh1Qcgax9KdYg9Xab5YKASAvHhRqy7KB6FLlDaLe5P3Ch5deJmgM6WZG0qpd1LJbF1BzMCCX/K1fbP8S2ULnx7U4FkEyeD6E5J11eWqkuJDPGm9cGAEUi4lwg7ybMBvll6FOZTKFO4a1OB3I4GdNgi0fLuUoaZrqeMyfLuhzsjED8syfVhsYlnoC3y8X5VygLhNTS5X6TT0LWJQMR/2LHF+Y6MlOGiNR5OqcKT0vg6ARqBhDfRnE1cDKLpCiNkKe1OXIfftIhnu30YPIidj3KtTrbAy5GzAWUEospgeTxPSe6ArVgUzdlNegQLh1OLu77Sc5k66ckHwHyc9AAsEifn75DG1wHQCCScSe7+mCvO2MhvfSpTrWBLgagnQ1sO0EmUzktuEAuHvChZNQLRPxvK5Z+LLm1ZDGoLgZSeRUQS5iMUwni7Ox3n/iYFfw9LAQ3nQRTmJnZQztp7gvBXxcCepLQ7fHMb5QUin/F9g33CQkq5wc9dK0ZZC3BzB9E7S5y1XwVhDyWrIpN7yhWbPTdpZQVSuouIBxXFs8r0e0rngycNVoo0+mAjEH1zxI4tzsKcqGhxAaXdw8rZ6FkgucRJEAnGlBvnKF1IK5uJkQEjED2TyY49FcAkZWvEJ1Oq8NtAAineRXLJW8CsI4PGjd1HOr+rHEhMDBiBqE8kO7Y4BTta2RLRLyiV73GLVY93kKJApjftC897GowByo4AT4OsE+O+xdoPT0Ygflgq34enJpvQWDxCK5HLbYsHjBWwrMPoko6FPXnUq0CKIpF941J+xHexdp9LdEqVyc+VNFKaU5/nQaQdiziwlIRaZHIJXk6tfGyt3acGr+wt7D4FUhSJngehDX4wLqKMe13E5yM094xAglOrkH2np8GKddD78sSfQMR7Zgui0I7MeZHyPhDdBca1lM5LZd3uK7Ao/9wIxP/ssJMcAcI4MJ/sH9VHT+LngIbj/Sz3fQmkeBfJ2WO6d/rKZMjuK64bYdFMasm/2FfHuPzcCKTvmeT25H7weDyA7/TdO1CP9+FZx9PEDrHjt8/mWyBrl1rJKQBf1qfV4B1WgzET4JmUKbwVHF5bCCOQnueLs4ldABJFioQ4+uuf2S23kyg/g2xsgB1bfG08R7/jRYvLQPxbdNHv0fXxXLr0g49CGqeqZo1ANqWfp+44EP36HQWPjgLhFECi4pmvGQ0mDmEy0B1knQ/s2A8CGOXLJ/lOIl3kfDA/hAbvnjilFjICAfga+3No5FGwrONKu8c/JX+p+EEGF4e0QIrLLdna035iKduHXwbhVTC5AFyA8/AsF8QuulbnafK7y6VNVxhYDwIp3hUa+ifBZMPybIBEelMbxOLfQyWzQMrNFGMyZVyp0nlSd5CN7iQ3hPAQJUdCLyiRIU+7UQWDcRCISt0/BeqCQxXT4ypfONKTHTxUaYQRiDR1PQJrQiCK4lBaYm3MXNRFYgRShwLRlPFT+Q6yfrmVS14oNqZo2reldUaNQLTSWTQW4TvI62BvAmWWztURtTaBFElzbHF+RGRGUTxHoiO0DTaMQPTyGVmBiBJ3oAmU6nhdV8RaBVIkrnWnARjQ2AaSTBqsK7KN7BiB6Cc1gneQmZR2J+iOVLtA1i+5sslTQcXSu2VPaukOpDd7RiD62Y6MQBiPAJhFGfdu/VFKfigM4ghn7fEgugTgqhX8NAIJMmP++kZAIM+Kiii91WHxF0nvvUK7g2z6lmvQzkDD92Hh/OLHogo3IxD9hFdNIMwvA9YsyuR/qj+qLS1WRCDrl13tuyTQuWZspYViBKL/UqqCQJYAuA5kzaJUx8f6IypvsaIC2UIoxKeA6EthB2sEop/higlE3DGI7sAq7zq6fOk7+iOJwBKrNxc4a38TRKcALHZxhrJhzQhE/2UVskA+BuhOMN8Z1sO3X0aqcgcp5xy3DRoCq/Fr3TXbDwDjAAAHgPScBzAC8Xs5+O+nWSAfAPgjgBdg8Uvo9BbQxGViSVX1FhmBlBVNNiFE8kWwyJpHQ2EVM1mInaDbBGHOCCQIW/76SgmE8R6AxSD8DeDFxX93NSykSR2v+Ru18r0iLZCe6OBc06fQ2DkAq3gA0G8gLG8APK/H02c0cen8ylPb84jSe9cilNWkKJDeWmPDKjCtAHUuR7+G5dj508vptFdWR2ke/PhSkwLxE1iU+8RBIFHmV6dvRiA62fRpywjEJ1ER6GYEUoVJMAKpAumSQxqBSBKnAjMCUWGvslgjkMryXRzNCKQKpEsOaQQiSZwKzAhEhb3KYo1AKsu3uYNUgW+VIY1AVNiTxJo7iCRxVYAZgVSBdCOQKpAuOaQRiCRxKjAjEBX2Kos1Aqks3+YZpAp8qwxpBKLCniTW3EEkiasCzAikCqQbgVSBdMkhjUAkiVOBGYGosFdZrBFIZfle+wySTRwDonmBh2ZcRxn3osA4A5BmwAhEmjp5IM/Y/j+weut3gp+Y5AsoXfiZ/MgGGZQBI5CgjGnqL1E5eDUsPoRaCn/W5IIx44MBIxAfJIXRhacl90MDv+DbNuEaSrlh1If07UI9djQCqeKss5O4BKD2Pl0g3Ecp98Q++5kO2hkwAtFOaTCDLBJTWJgFpmHlkXwhpQuzg1k1vXUxYASii0kFOzzb3gbLRV4w2gfEewP0TwCL0IWFNMl9SMG0gSoyYASiSKCBx5sBI5B4z6+JTpEBIxBFAg083gwYgcR7fk10igwYgSgSaODxZsAIJN7za6JTZMAIRJFAA483A0Yg8Z5fE50iA0YgigQaeLwZMAKJ9/ya6BQZMAJRJNDA482AEUi859dEp8iAEYgigQYebwaMQOI9vyY6RQb+HxRZw1dcj9WwAAAAAElFTkSuQmCC" />
        <div class="upload-title">点击上传</div>
        <div class="upload-tip" id="uploadTip"></div>
      </div>
      <div class="error-tip" id="errorTip"></div>
      <div class="panel-foot">
        <button class="foot-btn-back" onClick="onBack()">返回</button>
      </div>
    </div>
  </body>
  <script type="text/javascript">
    const urlParam = {}

    // 页面生命周期onload事件
    window.onload = () => {
      this.getUrlParam()
      const { tipFileType, fileType, maxSize, sizeUnit = 'M' } = urlParam
      const fileUploadDom = document.getElementById('fileUpload')
      fileType && fileUploadDom.setAttribute('accept', fileType)
      if (maxSize) {
        document.getElementById('uploadTip').innerText = `文件大小限制为${maxSize}${sizeUnit}`
      } else {
        document.getElementById('uploadTip').setAttribute('style', 'display: none')
      }
    }

    // 文件选择完成
    function onFileChange () {
      const file = document.getElementById('fileUpload').files[0]
      if (!file) {
        return
      }
      console.log(file)
      const errorTipDom = document.getElementById('errorTip')
      errorTipDom.innerText = ''
      const { tipFileType, fileType, maxSize, sizeUnit = 'M' } = urlParam
      const { name = '', size = 0 } = file
      if (fileType) {
        const nameSplitArray = name.split('.')
        if (!fileType.split(',').includes('.' + nameSplitArray[nameSplitArray.length - 1])) {
          errorTipDom.innerText = `请上传正确的${tipFileType || ''}文件`
          return
        }
      }
      if (maxSize) {
        const sizeUnitUpper = sizeUnit.toLocaleUpperCase()
        if ((sizeUnitUpper === 'M' && size / 1024 / 1024 > maxSize) 
          || (sizeUnitUpper === 'KB' && size / 1024 > maxSize)
          || (sizeUnitUpper === 'B' && size > maxSize)) {
            errorTipDom.innerText = `上传文件不能超过${maxSize}${sizeUnitUpper}`
            return
        }
      }
      const fileReader = new FileReader()
      fileReader.readAsDataURL(file)
      fileReader.onload = () => {
        const result = (fileReader.result || '').split(',')[1]
        if (result) {
          this.onPostMessage({ code: '0', fileInfo: { base64: result, name: file.name } })
          this.onBack()
        } else {
          errorTipDom.innerText = `读取文件失败`
        }
      }
      fileReader.error = () => {
        errorTipDom.innerText = `读取文件失败`
      }
    }
    
    // 打开选择文件对话框
    function onUploadClick () {
      document.getElementById('fileUpload').click()
    }

    // 给小程序发送消息
    function onPostMessage (value) {
      uni.postMessage({
        data: value
      })
    }

    // 返回小程序,相当于小程序的webview页面触发navigateBack方法,会触发webview页面的卸载事件(onUnload)
    function onBack () {
      wx.miniProgram.navigateBack()
    }

    // 获取url中的参数
    function getUrlParam() {
      const url = location.search
      const theRequest = new Object()
      if (url.indexOf("?") != -1) {
        const str = url.substr(1)
        const strs = str.split("&")
        for (let i = 0; i < strs.length; i++) {
          urlParam[strs[i].split("=")[0]] = decodeURIComponent(strs[i].split("=")[1])
        }
      }
    }
    
  </script>
</html>
<style>
  body {
    margin: 0;
  }
  .panel {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
  }
  #fileUpload {
    display: none;
  }
  .upload-view {
    margin-top: 30%;
    width: 70%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 2px dashed rgba(255, 141, 26, 1);
    border-radius: 10px;
    padding: 20px 0;
  }
  .upload-icon {
    width: 135px;
    height: 135px;
  }
  .upload-title, .upload-tip {
    margin-top: 10px;
  }
  .upload-title {
    color: rgba(255, 141, 26, 1);
    font-size: 20px;
  }
  .upload-tip {
    font-size: 12px;
    color: #333;
  }
  .upload-tip::before {
    content: '*';
    color: #F00;
    margin-right: 3px;
  }
  .error-tip {
    margin-top: 30px;
    color: #F00;
    font-size: 18px;
    font-weight: 550;
  }
  .panel-foot {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 10px;
  }
  .foot-btn-back {
    width: 100%;
    height: 45px;
    border-radius: 10px;
    border: 1px solid rgba(229, 229, 229, 1);
    background: transparent;
    color: rgba(166, 166, 166, 1);
    font-size: 17px;
  }
</style>

有个奇怪点,按uni官方文档说,是引入

https://gitcode.net/dcloud/uni-app/-/raw/dev/dist/uni.webview.1.5.6.js

但我在html文件里面不管是链接引入,还是下载到本地引入,都用不了uni的方法,最后换成了引入另一个才行。后面也不纠结研究了,总之能用就行。

html 复制代码
https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js

2:调后端接口返回html文件

我这边是通过后端接口返回html页面的,到时候就是webview页面调用后端接口,相当于一个完整链接,打开html页面。好像也可以把html文件放到小程序static里面,然后直接调用吧,没试过。

后端接口:

java 复制代码
    @RequestMapping("/sys/toFileUploadView")
    public void toFileUploadView(HttpServletResponse response) {
        try (
                OutputStream outputStream = response.getOutputStream();
                FileInputStream fileInputStream = new FileInputStream("存放html文件的路径");
        ){
            outputStream.write(IOUtils.toByteArray(fileInputStream));
        } catch (IOException e) {
            log.error("打开pc端文件上传页面失败", e);
        }
    }

小程序上传按钮代码:

javascript 复制代码
onUploadExcelFile () {
	uni.getSystemInfo({
		success: res => {
			if (['windows', 'mac'].includes(res.platform)) {
				// PC端
				// 通过webview页面打开我们写的html文件
				/**
				 * url参数:
				 *  tipFileType: 上传文件不符合时,提示应该上传什么文件
				 *  fileType:支持文件的后缀名
				 *  maxSize:文件大小限制
				 *  sizeUnit:文件大小限制的单位(m, kb, b)
				 */
				// 下面这段url参数意思是:只能上传.xls或.xlsx的文件,当上传文件类型不对时,提示请上传正确的excel文件,然后文件最大只能500kb
				uni.navigateTo({
					url: `/pages/webView/webView?url=${encodeURIComponent('自己的域名或者ip 比如:https://baidu.com' + '/sys/toFileUploadView?tipFileType=excel&fileType=.xls,.xlsx&maxSize=500&sizeUnit=KB')}`
				})
			} else {
				// 手机端
				// 自己写代码调用 wx.chooseMessageFile API
			}
		}
	})
}

3:小程序webview页面

里面有很多注释说明,记得看

javascript 复制代码
<template>
	<view>
		<web-view :src="url" @message="onMessage"></web-view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				url: '',
				webMessageList: void (0)
			}
		},
		onLoad(options) {
			this.url = decodeURIComponent(options.url)
			if (options.title) {
				uni.setNavigationBarTitle({
					title: decodeURIComponent(options.title)
				})
			}
		},

		/**
		 * 外部页面(html页面)调用wx.miniProgram.navigateBack()后触发
		 */
		onUnload () {
			const pages = getCurrentPages()
			if (pages.length > 1) {
				const { route } = pages[pages.length - 2]
				/**
				 * 判断小程序路由栈里当前webview页面的上一个页面是否是指定页面
				 */
				if (['你的页面'].includes(route)) {
					if ((this.webMessageList || []).length) {
						const { fileInfo = {} } = this.webMessageList[0]
						if (fileInfo.base64) {
							/**
							 * 如果是指定页面并有接收到消息,则取出文件的base64
							 * 这里注意:如果你是打算通过uni.setStroageSync设置缓存,然后指定页面的onShow方法接收处理,
							 * 			我只能告诉你,如果文件太大,缓存还没设置完,
							 * 			此页面已经卸载完成了,然后触发上一个页面的onShow的时候,你取缓存就是空,
							 * 			如果你说加setTimeout延迟获取缓存,那延迟的时间该是多少呢,不可靠!
							 * 			我的做法是设置uni.setStroageSync缓存的同时,设置一个store缓存,值简单点,true就行了
							 * 			设置store缓存肯定会在页面卸载完成前设置完成。
							 * 			对应页面的show方法看文章后面!
							 */
							// store.commit('store缓存key', true)
							// uni.setStroageSync('文件内容缓存key', fileInfo.base64)
							// uni.showLoading({
							// 	mask: true,
							// 	title: '请稍候...'
							// })
						}
					}
				}
			}
		},

		methods: {

			/**
			 * 接收webview打开的外部页面发送过来的消息
			 * 有点不好的是,外部页面发送的消息这里并不能实时获取,必须触发页面返回也就是调用navigateBack等方法才会接收到外部页面的消息
			 * 在我们写的html页面里面调用wx.miniProgram.navigateBack() 会触发webview页面的消息接收
			 * 调用wx.miniProgram.navigateBack()后执行方法顺序是:onMessage -> onUnload
			 * 也就是接收到外部页面消息后,webview页面就马上关闭了
			 */
			onMessage ({ detail }) {
				const { data = [] } = detail || {}
				if (data.length) {
					this.webMessageList = data
				}
			}
		}
	}
</script>

<style>

</style>

4:对应功能页面的show方法

javascript 复制代码
async onShow () {
	if ('取store缓存') {
		const waitTime = (millisecond) => {
			return new Promise((resolve, reject) => {
				setTimeout(() => {
					resolve()
				}, millisecond)
			})
		}
		while (true) {
			if ('store缓存不存在或者不为true') {
				uni.hideLoading()
				break
			}
			const base64 = uni.getStorageSync('文件base64内容缓存key')
			if (base64) {
				// 取到文件内容了,自己处理了...
				store.commit('store缓存key', false)
				uni.hideLoading()
				break
			}
			// 本次循环遍历结束,文件base64内容缓存还没设置完成,等待500毫秒,继续下一次检查
			await waitTime(500)
		}
	}
}

好了,到这就结束了,有问题留言。如果你们碰到小程序上线后webview页面通过后端接口打不开html文件的,检查一下小程序后台管理业务域名这些配置上没有。


码字不易,于你有利,勿忘点赞

相关推荐
快乐的二进制鸭7 小时前
uniapp实现app的pdf预览
pdf·uni-app
盛夏绽放8 小时前
微信小程序地图map全方位解析
微信小程序·小程序
qq_316837759 小时前
uniapp 打包安卓 集成高德地图
uni-app
阿福的工作室9 小时前
uniapp录制语音
uni-app
初尘屿风11 小时前
基于微信小程序的电影院订票选座系统的设计与实现,SSM+Vue+毕业论文+开题报告+任务书+指导搭建视频
vue.js·微信小程序·小程序
貂蝉空大11 小时前
uni-app开发app时 使用uni.chooseLocation遇到的问题
uni-app
林同学++11 小时前
uniapp多端适配
uni-app
kidding72311 小时前
uniapp引入uview组件库(可以引用多个组件)
前端·前端框架·uni-app·uview
qq_3168377511 小时前
uniapp 安卓10+ 选择并上传文件
uni-app
合法的咸鱼11 小时前
uniapp 使用unplugin-auto-import 后, vue文件报红问题
前端·vue.js·uni-app