사용자가 대용량 파일을 업로드할 때 네트워크 연결이 좋지 않으면 몇 시간이 걸릴 수 있습니다. 회선이 중단되면 재개 가능한 업로드가 없는 서버는 처음부터 다시 전송만 가능하며 재개 가능한 업로드가 허용됩니다. . 사용자는 업로드가 끊어진 곳에서 계속 전송할 수 있으므로 사용자의 걱정이 크게 줄어듭니다.
대용량 파일 업로드 시 서버 메모리 부족 문제 해결
다른 요인으로 인해 업로드가 종료된 경우 문제를 해결하고, 브라우저를 새로고침하고 브라우저를 다시 시작하면 업로드가 재개됩니다(닫기) 브라우저를 열고 열 수 있음) 계속 업로드할 수 있으며, 컴퓨터를 다시 시작해도 업로드할 수 있습니다
업로드 프로세스 중 네트워크 변동으로 인한 파일 콘텐츠 손실을 감지한 후 자동으로 감지하여 다시 업로드해야 합니다
Front-end
필수 분할 업로드 파일의 경우
, 업로드된 분할 파일의 파일 일련번호를 지정해야 합니다
업로드 진행 상황을 모니터링하고 진행률 표시줄 제어
업로드가 완료된 후 병합 요청을 보내야 합니다
Blob 개체, 파일 조작
Backend
샤드 업로드용 인터페이스
병합용 인터페이스 shards
샤드 가져오기를 위한 인터페이스
지원을 위한 다른 도구 방법
프론트엔드에서 주의해야 할 것은: 파일 자르기 및 진행률 표시줄
백엔드에서 주의해야 할 것
먼저 업로드해야 할 파일을 찾으세요
업로드가 시작되면 업로드 중지를 클릭하면 진행률 표시줄이 변경됩니다.
백엔드는 파일 이름 + 파일 크기를 MD5에 사용하여 다음과 같이 해당 디렉터리 결과를 생성합니다.
프런트 엔드에 업로드된 파일이 100%에 도달하면, 파일 병합 요청이 전송되면 백엔드의 모든 샤드가 하나의 파일로 병합됩니다
아래 그림에서 볼 수 있듯이 모든 샤드가 사라졌으므로 파일을 병합하세요
파일 업로드 프로세스 중 네트워크 변동으로 인해 스트림 일부가 손실되었습니다(크기 비교)
파일 업로드 프로세스 중에 서버에서 조각이 손실되었습니다(비교 조각 연속성)
다음의 변조된 콘텐츠 파일 (비교 크기)
검증 코어 코드
<!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>Document</title> </head> <body> <h2>html5大文件断点切割上传</h2> <div id="progressBar"></div> <input id="file" name="mov" type="file" /> <input id="btn" type="button" value="点我上传" /> <input id="btn1" type="button" value="点我停止上传" /> <script type="module"> import FileSliceUpload from '../jsutils/FileSliceUpload.js' let testingUrl="http://localhost:7003/fileslice/testing" let uploadUrl="http://localhost:7003/fileslice/uploads" let margeUrl="http://localhost:7003/fileslice/merge-file-slice" let progressUrl="http://localhost:7003/fileslice/progress" let fileSliceUpload= new FileSliceUpload(testingUrl,uploadUrl,margeUrl,progressUrl,"#file") fileSliceUpload.addProgress("#progressBar") let btn= document.querySelector("#btn") let btn1= document.querySelector("#btn1") btn.addEventListener("click",function () { fileSliceUpload.startUploadFile() }) btn1.addEventListener("click",function () { fileSliceUpload.stopUploadFile() }) </script> </body> </html>rrree
코드에서 자체 캡슐화된 도구 클래스를 더 많이 사용하기 때문에 다음 코드만 원리에 대한 참조를 제공합니다
//大文件分片上传,比如10G的压缩包,或者视频等,这些文件太大了 (需要后端配合进行) class FileSliceUpload{ constructor(testingUrl, uploadUrl, margeUrl,progressUrl, fileSelect) { this.testingUrl = testingUrl; // 检测文件上传的url this.uploadUrl = uploadUrl;//文件上传接口 this.margeUrl = margeUrl; // 合并文件接口 this.progressUrl = progressUrl; //进度接口 this.fileSelect = fileSelect; this.fileObj = null; this.totalize = null; this.blockSize = 1024 * 1024; //每次上传多少字节1mb(最佳) this.sta = 0; //起始位置 this.end = this.sta + this.blockSize; //结束位置 this.count = 0; //分片个数 this.barId = "bar"; //进度条id this.progressId = "progress";//进度数值ID this.fileSliceName = ""; //分片文件名称 this.fileName = ""; this.uploadFileInterval = null; //上传文件定时器 } /** * 样式可以进行修改 * @param {*} progressId 需要将进度条添加到那个元素下面 */ addProgress (progressSelect) { let bar = document.createElement("div") bar.setAttribute("id", this.barId); let num = document.createElement("div") num.setAttribute("id", this.progressId); num.innerText = "0%" bar.appendChild(num); document.querySelector(progressSelect).appendChild(bar) } //续传 在上传前先去服务器检测之前是否有上传过这个文件,如果还有返回上传的的分片,那么进行续传 // 将当前服务器上传的最后一个分片会从新上传, 避免因为网络的原因导致分片损坏 sequelFile () { if (this.fileName) { var xhr = new XMLHttpRequest(); //同步 xhr.open('GET', this.testingUrl + "/" + this.fileName+ "/" + this.blockSize+ "/" + this.totalize, false); xhr.send(); if (xhr.readyState === 4 && xhr.status === 200) { let ret = JSON.parse(xhr.response) if (ret.code == 20000) { let data= ret.data this.count = data.code; this.fileSliceName = data.fileSliceName //计算起始位置和结束位置 this.sta = this.blockSize * this.count //计算结束位置 this.end = this.sta + this.blockSize } else { this.sta = 0; //从头开始 this.end = this.sta + this.blockSize; this.count = 0; //分片个数 } } } } stopUploadFile () { clearInterval(this.uploadFileInterval) } // 文件上传(单文件) startUploadFile () { // 进度条 let bar = document.getElementById(this.barId) let progressEl = document.getElementById(this.progressId) this.fileObj = document.querySelector(this.fileSelect).files[0]; this.totalize = this.fileObj.size; this.fileName = this.fileObj.name; //查询是否存在之前上传过此文件,然后继续 this.sequelFile() let ref = this; //拿到当前对象的引用,因为是在异步中使用this就是他本身而不是class this.uploadFileInterval = setInterval(function () { if (ref.sta > ref.totalize) { //上传完毕后结束定时器 clearInterval(ref.uploadFileInterval) //发送合并请求 ref.margeUploadFile () console.log("stop" + ref.sta); return; }; //分片名称 ref.fileSliceName = ref.fileName + "-slice-" + ref.count++ //分割文件 , var blob1 = ref.fileObj.slice(ref.sta, ref.end); var fd = new FormData(); fd.append('part', blob1); fd.append('fileSliceName', ref.fileSliceName); fd.append('fileSize', ref.totalize); var xhr = new XMLHttpRequest(); xhr.open('POST', ref.uploadUrl, true); xhr.send(fd); //异步发送文件,不管是否成功, 会定期检测 xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { let ret = JSON.parse(xhr.response) if (ret.code == 20000) { //计算进度 let percent = Math.ceil((ret.data*ref.blockSize/ ref.totalize) * 100) if (percent > 100) { percent=100 } bar.style.width = percent + '%'; bar.style.backgroundColor = 'red'; progressEl.innerHTML = percent + '%' } } } //起始位置等于上次上传的结束位置 ref.sta = ref.end; //结束位置等于上次上传的结束位置+每次上传的字节 ref.end = ref.sta + ref.blockSize; }, 5) } margeUploadFile () { console.log("检测上传的文件完整性.........."); var xhr = new XMLHttpRequest(); //文件分片的名称/分片大小/总大小 xhr.open('GET', this.margeUrl+ "/" + this.fileSliceName + "/" + this.blockSize + "/" + this.totalize, true); xhr.send(); //发送请求 xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { let ret = JSON.parse(xhr.response) if (ret.code == 20000) { console.log("文件上传完毕"); } else { console.log("上传完毕但是文件上传过程中出现了异常", ret); } } } } } export default FileSliceUpload;
위 내용은 Java를 사용하여 파일의 중단점 재개 기능을 구현하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!