html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文件上传</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
width: 400px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 20px;
}
.heading {
font-size: 24px;
text-align: center;
margin-bottom: 20px;
}
.description {
font-size: 18px;
margin-bottom: 20px;
}
.upload-button {
display: block;
margin: 0 auto;
text-align: center;
width: 80px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 4px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.label {
display: inline-block;
text-align: center;
}
.upload-button:hover {
background-color: #0056b3;
}
#fileItem {
position: absolute;
left: -999px;
opacity: 0;
}
/* 全屏遮罩样式 */
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 24px;
z-index: 1000;
flex-direction: column;
}
.spinner {
width: 60px;
height: 60px;
border: 6px solid rgba(255, 255, 255, 0.3);
border-top: 6px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 30px;
display: block;
margin-left: auto;
margin-right: auto;
}
.loading-content {
background: rgba(255, 255, 255, 0.1);
padding: 30px 50px;
border-radius: 10px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.filename {
font-size: 18px;
color: #007bff;
margin-bottom: 15px;
word-break: break-all;
max-width: 300px;
}
.loading-text {
font-size: 20px;
color: #ffffff;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.error-content {
background: rgba(255, 0, 0, 0.1);
padding: 30px 50px;
border-radius: 10px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.error-text {
font-size: 20px;
color: #ff0000;
margin-bottom: 15px;
}
.error-button {
background-color: #ff3b30;
color: white;
border: none;
border-radius: 4px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
margin-top: 20px;
}
.error-button:hover {
background-color: #dc3545;
}
</style>
</head>
<body>
<div class="container" id="uploadContainer">
<h1 class="heading">文件上传</h1>
<p class="description">操作步骤</p>
<p class="description">1、点击一键上传</p>
<p class="description">2、请选择您要上传的文件</p>
<label for="fileItem" class="upload-button" id="uploadButton"> 一键上传 </label>
<input id="fileItem" type="file" />
</div>
<script src="../jweixin-1.3.2.js"></script>
<script src="../spark-md5.min.js"></script>
<script>
var fileInput = document.getElementById('fileItem')
fileInput.addEventListener('change', function (event) {
var selectedFile = event.target.files[0]
if (selectedFile) {
var reader = new FileReader()
var spark = new SparkMD5()
reader.onload = function (loadEvent) {
// 计算文件md5值
spark.append(loadEvent.target.result)
var md5Hash = spark.end()
// 截取文件base64
var base64Data = loadEvent.target.result.split(',')[1]
// 获取文件大小
var fileSize = selectedFile.size
var name = selectedFile.name
var data = {
base64Data: base64Data,
md5Hash: md5Hash,
fileSize: fileSize,
name: name,
}
wx.miniProgram.postMessage({
data: data,
})
wx.miniProgram.redirectTo({
url: '../upload/upload?loading=1', // 关键代码,重置webview页面,重新触发onLoad
})
}
reader.readAsDataURL(selectedFile)
}
})
</script>
<script>
function getQueryParameter(name) {
const urlParams = new URLSearchParams(window.location.search)
return urlParams.get(name)
}
// 检查 query 中是否有 loading 参数
if (getQueryParameter('loading')) {
// 隐藏上传容器
const uploadContainer = document.getElementById('uploadContainer')
if (uploadContainer) {
uploadContainer.style.display = 'none'
}
// 获取文件名
const filename = getQueryParameter('name') || '上传的文件名称'
// 显示遮罩
const overlay = document.createElement('div')
overlay.className = 'overlay'
// 创建加载内容容器
const loadingContent = document.createElement('div')
loadingContent.className = 'loading-content'
// 创建加载动画
const spinner = document.createElement('div')
spinner.className = 'spinner'
// 创建文件名显示
const filenameDiv = document.createElement('div')
filenameDiv.className = 'filename'
filenameDiv.textContent = filename
// 创建文本提示
const text = document.createElement('div')
text.className = 'loading-text'
text.textContent = '正在上传中,请稍后...'
loadingContent.appendChild(spinner)
loadingContent.appendChild(filenameDiv)
loadingContent.appendChild(text)
overlay.appendChild(loadingContent)
document.body.appendChild(overlay)
}
</script>
<script>
if (getQueryParameter('error')) {
// 隐藏上传容器
const uploadContainer = document.getElementById('uploadContainer')
if (uploadContainer) {
uploadContainer.style.display = 'none'
}
// 显示错误遮罩
const overlay = document.createElement('div')
overlay.className = 'overlay'
// 创建错误内容容器
const errorContent = document.createElement('div')
errorContent.className = 'error-content'
// 创建错误文本
const errorText = document.createElement('div')
errorText.className = 'error-text'
errorText.textContent = '上传失败,请重试。'
// 创建返回按钮
const backButton = document.createElement('button')
backButton.className = 'error-button'
backButton.textContent = '返回'
backButton.onclick = function () {
// 返回原始页面
wx.miniProgram.navigateBack()
}
errorContent.appendChild(errorText)
errorContent.appendChild(backButton)
overlay.appendChild(errorContent)
document.body.appendChild(overlay)
}
</script>
</body>
</html>
js
// pages/upload/upload.js
/**
* 1. 初始进入页面,直接加载webview
* 2. webview中选择文件后,使用redirectTo(upload)刷新页面,来触发bindMessage
* 3. bindMessage进行上传逻辑
* 4. 上传时redirect(upload),更新webview为加载态
* 5. 上传成功就回退页面
* 6. 上传失败redirect(upload)刷新页面,更新webview为错误态
*/
Page({
data: {
_webviewUrl: 'http://127.0.0.1:5500/index.html',
},
options: {},
dataInfo: {},
onLoad: function (options) {
const eventChannel = this.getOpenerEventChannel()
eventChannel &&
eventChannel.on &&
eventChannel.on('dataInfo', data => {
this.dataInfo = data
})
this.options = options
if (options.loading) {
this.setData({
_webviewUrl: this.data._webviewUrl + '?loading=1&name=filename.pdf', // 关键代码,刷新webview为loading态
})
}
if (options.error) {
this.setData({
_webviewUrl: this.data._webviewUrl + '?error=1', // 关键代码,刷新webview为error态
})
}
},
bindMessage(e) {
const data = e.detail.data[0]
console.log('我要上传', this.dataInfo.id)
setTimeout(() => {
if (Math.random() > 0.2) {
console.log('上传', this.dataInfo.id, '成功')
wx.navigateBack() // 上传成功
} else {
console.log('上传', this.dataInfo.id, '失败')
// 上传失败
wx.redirectTo({
url: '../upload/upload?error=1', // 关键代码,重置webview页面,重新触发onLoad
})
}
}, 2000)
},
})