<!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>