You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
6.9 KiB
HTML
186 lines
6.9 KiB
HTML
9 months ago
|
<!DOCTYPE html>
|
||
|
<html>
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
<title>B612 File Upload Page</title>
|
||
|
<link rel="stylesheet" href="/css?bootstrap=true">
|
||
|
<script src="/js?jquery=true"></script>
|
||
|
<style>
|
||
|
@media (max-width: 600px) {
|
||
|
.progress-bar, p {
|
||
|
width: 100%;
|
||
|
}
|
||
|
}
|
||
|
.file-upload {
|
||
|
border: 1px solid #ddd;
|
||
|
padding: 10px;
|
||
|
margin-bottom: 10px;
|
||
|
border-radius: 5px;
|
||
|
background-color: #f9f9f9;
|
||
|
}
|
||
|
</style>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="container">
|
||
|
<h1 class="text-center">B612 File Upload Page</h1>
|
||
|
<form id="uploadForm" action="/recv?upload=true" method="post" enctype="multipart/form-data">
|
||
|
<div class="form-group">
|
||
|
<label for="victorique">上传文件:</label>
|
||
|
<input type="file" class="form-control-file" id="victorique" name="victorique" multiple>
|
||
|
</div>
|
||
|
<button type="submit" class="btn btn-primary">上传</button>
|
||
|
<button type="button" id="clearButton" class="btn btn-secondary">清除</button>
|
||
|
<button type="button" id="cancelAllButton" class="btn btn-danger">取消所有上传</button>
|
||
|
</form>
|
||
|
<div id="progressContainer"></div>
|
||
|
</div>
|
||
|
<script>
|
||
|
var completedUploads = 0;
|
||
|
var anyUploadFailed = false;
|
||
|
var xhrs = []; // Array to hold all the XHR objects
|
||
|
|
||
|
$("#victorique").on("change", function(e){
|
||
|
document.getElementById('progressContainer').innerHTML = '';
|
||
|
var files = document.getElementById('victorique').files;
|
||
|
for (var i = 0; i < files.length; i++) {
|
||
|
createProgressBar(files[i]);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$("#clearButton").on("click", function(e){
|
||
|
document.getElementById('victorique').value = '';
|
||
|
document.getElementById('progressContainer').innerHTML = '';
|
||
|
});
|
||
|
|
||
|
$("#cancelAllButton").on("click", function(e){
|
||
|
for (var i = 0; i < xhrs.length; i++) {
|
||
|
xhrs[i].abort();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$("#uploadForm").on("submit", function(e){
|
||
|
e.preventDefault();
|
||
|
completedUploads = 0; // Reset the counter
|
||
|
anyUploadFailed = false; // Reset the flag
|
||
|
var files = document.getElementById('victorique').files;
|
||
|
var fileUploads = document.querySelectorAll('.file-upload');
|
||
|
for (var i = 0; i < files.length; i++) {
|
||
|
uploadFile(files[i], fileUploads[i]);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
function createProgressBar(file) {
|
||
|
var progressContainer = document.getElementById('progressContainer');
|
||
|
var fileUpload = document.createElement('div');
|
||
|
fileUpload.className = 'file-upload';
|
||
|
progressContainer.appendChild(fileUpload);
|
||
|
var fileNameLabel = document.createElement('p');
|
||
|
fileNameLabel.innerHTML = file.name;
|
||
|
fileUpload.appendChild(fileNameLabel);
|
||
|
var progressBar = document.createElement('div');
|
||
|
progressBar.className = 'progress-bar';
|
||
|
progressBar.setAttribute('role', 'progressbar');
|
||
|
progressBar.style.width = '0%';
|
||
|
progressBar.setAttribute('aria-valuenow', '0');
|
||
|
progressBar.setAttribute('aria-valuemin', '0');
|
||
|
progressBar.setAttribute('aria-valuemax', '100');
|
||
|
fileUpload.appendChild(progressBar);
|
||
|
var speedLabel = document.createElement('p');
|
||
|
var sizeLabel = document.createElement('p');
|
||
|
var cancelButton = document.createElement('button');
|
||
|
cancelButton.innerHTML = '取消上传';
|
||
|
cancelButton.className = 'btn btn-danger';
|
||
|
fileUpload.appendChild(speedLabel);
|
||
|
fileUpload.appendChild(sizeLabel);
|
||
|
fileUpload.appendChild(cancelButton);
|
||
|
|
||
|
// Save these elements as custom properties
|
||
|
fileUpload.progressBar = progressBar;
|
||
|
fileUpload.speedLabel = speedLabel;
|
||
|
fileUpload.sizeLabel = sizeLabel;
|
||
|
fileUpload.cancelButton = cancelButton;
|
||
|
return fileUpload;
|
||
|
}
|
||
|
|
||
|
function uploadFile(file, fileUpload) {
|
||
|
var formData = new FormData();
|
||
|
formData.append('victorique', file);
|
||
|
var start = Date.now();
|
||
|
var lastLoaded = 0;
|
||
|
var progressBar = fileUpload.progressBar;
|
||
|
var speedLabel = fileUpload.speedLabel;
|
||
|
var sizeLabel = fileUpload.sizeLabel;
|
||
|
var cancelButton = fileUpload.cancelButton;
|
||
|
|
||
|
var xhr = $.ajax({
|
||
|
xhr: function(){
|
||
|
var xhr = new window.XMLHttpRequest();
|
||
|
xhr.upload.addEventListener("progress", function(evt){
|
||
|
if(evt.lengthComputable){
|
||
|
var percentComplete = ((evt.loaded / evt.total) * 100).toFixed(2);
|
||
|
var timeElapsed = (Date.now() - start) / 1000; // Time elapsed in seconds
|
||
|
var bytesLoaded = evt.loaded - lastLoaded;
|
||
|
lastLoaded = evt.loaded;
|
||
|
var speed = bytesLoaded / timeElapsed; // Speed in bytes/second
|
||
|
var formattedSpeed = formatSize(speed);
|
||
|
progressBar.style.width = percentComplete + '%';
|
||
|
progressBar.innerHTML = percentComplete + '%';
|
||
|
speedLabel.innerHTML = "上传速度: " + formattedSpeed + "/秒";
|
||
|
sizeLabel.innerHTML = "已上传: " + formatSize(evt.loaded) + " / " + formatSize(evt.total);
|
||
|
start = Date.now();
|
||
|
}
|
||
|
}, false);
|
||
|
return xhr;
|
||
|
},
|
||
|
url: '/recv?upload=true',
|
||
|
type: 'POST',
|
||
|
data: formData,
|
||
|
cache: false,
|
||
|
contentType: false,
|
||
|
processData: false,
|
||
|
success: function(response){
|
||
|
completedUploads++;
|
||
|
if (completedUploads === document.getElementById('victorique').files.length) {
|
||
|
if (anyUploadFailed) {
|
||
|
alert('一些文件上传失败!');
|
||
|
} else {
|
||
|
alert('所有文件上传成功!');
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
error: function(response){
|
||
|
anyUploadFailed = true;
|
||
|
completedUploads++;
|
||
|
if (completedUploads === document.getElementById('victorique').files.length) {
|
||
|
alert('一些文件上传失败!');
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
xhrs.push(xhr); // Add the XHR object to the array
|
||
|
|
||
|
// Add click event to the cancel button
|
||
|
cancelButton.onclick = function() {
|
||
|
xhr.abort();
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function formatSize(size) {
|
||
|
var i = 0;
|
||
|
var units = ['字节', 'KB', 'MB', 'GB'];
|
||
|
while (size >= 1024) {
|
||
|
size /= 1024;
|
||
|
i++;
|
||
|
}
|
||
|
return size.toFixed(2) + ' ' + units[i];
|
||
|
}
|
||
|
</script>
|
||
|
<footer class="footer mt-auto py-3">
|
||
|
<div class="container text-center">
|
||
|
<span class="text-muted">Copyright@b612.me</span>
|
||
|
</div>
|
||
|
</footer>
|
||
|
</body>
|
||
|
</html>
|