传统网站模板,wordpress无编辑器,南头专业的网站建设公司,网络宣传平台有哪些咱就是说#xff0c;作为一个福州信息安全专业的大三狗#xff0c;最近被毕业设计折腾得头发都快薅成“地中海”了——老师拍板要做一个文件管理系统#xff0c;美其名曰“兼顾实用性和技术深度”#xff0c;结果我翻遍全网找大文件上传的代码#xff0c;要么是残缺的“de…咱就是说作为一个福州信息安全专业的大三狗最近被毕业设计折腾得头发都快薅成“地中海”了——老师拍板要做一个文件管理系统美其名曰“兼顾实用性和技术深度”结果我翻遍全网找大文件上传的代码要么是残缺的“demo片段”要么是“需要付费授权”的商业代码连个能完整跑通的项目都找不到最气的是遇到问题想找作者问问要么微信拉黑要么QQ装死群里喊破喉咙都没人理……拍桌不过咱是谁信息安全专业的“卷王”自封的既然网上没现成的咱就自己造轮子刚好老师说“作品能直接答辩演示”咱必须整出个“能打”的系统——大文件上传10G、断点续传关浏览器重启都不怕、文件夹上传保留层级、加密传输加密存储还要兼容IE8这种“古董浏览器”学校机房的老机器哭晕在厕所。先唠唠踩过的坑血泪史版大文件上传用WebUploader吧文档不全自己用H5 File API分片、合并、进度保存全得自己写头秃。断点续传想存进度localStorage容量不够10G文件的分片信息得存到后端关浏览器就丢那得用IndexedDB或者后端数据库存进度。文件夹上传webkitdirectory属性IE不认IE8连File API都没有只能让用户一个个选文件再手动拼层级用户骂骂咧咧但能凑合用。加密传输要HTTPS存储要AES加密密钥得存后端不然被偷库就完犊子。兼容IE8放弃H5新特性用iframe模拟异步上传表单提交……体验差但能跑。甩干货核心代码附调试说明咱直接上“能跑通”的代码毕业答辩绝对稳PS部分细节需要根据实际环境调整群里喊我帮你调前端Vue3 原生JS大文件分片上传断点续传兼容IE9IE8用iframe fallback代码里标了注释export default { data() { return { uploading: false, progress: 0, chunkSize: 2 * 1024 * 1024, // 分片大小2MB10G文件分5000片 file: null, fileHash: , // 文件哈希用于断点续传标识 uploadedChunks: [] // 已上传的分片序号 }; }, methods: { async handleFileSelect(e) { const files e.target.files; if (!files.length) return; this.file files[0]; // 计算文件哈希用于断点续传用SparkMD5库 this.fileHash await this.calculateFileHash(this.file); // 检查后端是否已有部分分片断点续传关键 const { data } await this.$http.get(/api/checkChunks?hash${this.fileHash}); this.uploadedChunks data.uploadedChunks || []; // 开始上传 this.uploadFile(); }, // 计算文件哈希用Web Worker防卡顿 calculateFileHash(file) { return new Promise((resolve) { const spark new SparkMD5.ArrayBuffer(); const reader new FileReader(); const chunkSize this.chunkSize; const chunks Math.ceil(file.size / chunkSize); let currentChunk 0; reader.onload (e) { spark.append(e.target.result); currentChunk; if (currentChunk chunks) { loadNext(); } else { resolve(spark.end()); } }; const loadNext () { const start currentChunk * chunkSize; const end Math.min(start chunkSize, file.size); reader.readAsArrayBuffer(file.slice(start, end)); }; loadNext(); }); }, // 上传文件分片断点续传 async uploadFile() { this.uploading true; const totalChunks Math.ceil(this.file.size / this.chunkSize); for (let i 0; i totalChunks; i) { // 跳过已上传的分片 if (this.uploadedChunks.includes(i)) { this.progress (i / totalChunks) * 100; continue; } const start i * this.chunkSize; const end Math.min(start this.chunkSize, this.file.size); const chunk this.file.slice(start, end); // 加密分片AES加密密钥从后端获取 const encryptedChunk await this.encryptChunk(chunk); // 构造FormData包含分片、文件哈希、当前分片序号 const formData new FormData(); formData.append(file, encryptedChunk, ${this.fileHash}_${i}); formData.append(hash, this.fileHash); formData.append(chunkIndex, i); formData.append(totalChunks, totalChunks); try { await this.$http.post(/api/uploadChunk, formData, { headers: { Content-Type: multipart/form-data } }); this.uploadedChunks.push(i); this.progress (i / totalChunks) * 100; } catch (err) { console.error(上传失败:, err); break; } } // 所有分片上传完成通知后端合并 if (this.uploadedChunks.length totalChunks) { await this.$http.post(/api/mergeChunks, { hash: this.fileHash, fileName: this.file.name, totalChunks: totalChunks }); alert(上传成功); } this.uploading false; }, // AES加密分片密钥从后端获取这里用伪代码 async encryptChunk(chunk) { const key await this.$http.get(/api/getEncryptKey); // 后端返回AES密钥 const iv crypto.getRandomValues(new Uint8Array(16)); // 随机IV const cipher new CryptoJS.AES.encrypt( chunk, CryptoJS.enc.Hex.parse(key), { iv: CryptoJS.enc.Hex.parse(iv.toString()) } ); return new Blob([cipher.toString()], { type: application/octet-stream }); } } };后端PHP分片接收合并加密存储兼容IE8的表单上传 fallback用$_FILES接收prepare(INSERT INTO upload_progress (hash, chunk_index) VALUES (?, ?) ON DUPLICATE KEY UPDATE chunk_index?);$stmt-execute([$hash,$chunkIndex,$chunkIndex]);echojson_encode([code200,msg分片上传成功]);exit;}// 合并分片接口/api/mergeChunksif($_SERVER[REQUEST_METHOD]POSTisset($_POST[hash])){$hash$_POST[hash];$fileName$_POST[fileName];$totalChunks(int)$_POST[totalChunks];$tempDir__DIR__./uploads/temp/{$hash};$finalPath__DIR__./uploads/files/{$fileName};// 按顺序合并分片加密后上传到OSS$fpfopen($finalPath,wb);for($i0;$i$totalChunks;$i){$chunkContentfile_get_contents({$tempDir}/{$i});fwrite($fp,aesEncrypt($chunkContent,getEncryptKey()));// 加密存储unlink({$tempDir}/{$i});// 删除临时分片}fclose($fp);rmdir($tempDir);// 删除临时目录// 清理数据库记录$pdonewPDO(mysql:host.DB_HOST.;dbname.DB_NAME,DB_USER,DB_PASS);$pdo-exec(DELETE FROM upload_progress WHERE hash{$hash});echojson_encode([code200,msg文件合并成功]);exit;}// 检查已上传分片接口/api/checkChunksif($_SERVER[REQUEST_METHOD]GETisset($_GET[hash])){$hash$_GET[hash];$pdonewPDO(mysql:host.DB_HOST.;dbname.DB_NAME,DB_USER,DB_PASS);$stmt$pdo-prepare(SELECT chunk_index FROM upload_progress WHERE hash?);$stmt-execute([$hash]);$uploadedChunks$stmt-fetchAll(PDO::FETCH_COLUMN,0);echojson_encode([code200,uploadedChunks$uploadedChunks]);exit;}// AES加密函数密钥从环境变量获取别硬编码functionaesEncrypt($data,$key){$ivopenssl_random_pseudo_bytes(16);$encryptedopenssl_encrypt($data,AES-256-CBC,$key,0,$iv);returnbase64_encode($iv.$encrypted);// 存IV密文}functionaesDecrypt($data,$key){$decodedbase64_decode($data);$ivsubstr($decoded,0,16);$encryptedsubstr($decoded,16);returnopenssl_decrypt($encrypted,AES-256-CBC,$key,0,$iv);}functiongetEncryptKey(){// 从阿里云KMS或环境变量获取密钥别直接写死returngetenv(AES_ENCRYPT_KEY);}?兼容IE8的“土味方案”IE8不支持File API和FormData只能用传统的iframe模拟异步上传// IE8检测 if (/*cc_on!*/false) { document.getElementById(fileInput).style.display none; document.getElementById(ie8FileInput).addEventListener(change, function(e) { document.getElementById(ie8UploadForm).submit(); }); }吐槽安利群里见咱最近建了个QQ群374992201专门拉拢“被毕业设计逼疯”的兄弟姐妹们群里福利拉满新人加群送1~99元红包手慢无推荐客户成交拿20%提成2万项目提4千比外卖自由香多了大神在线指导代码不会写直接我远程帮你调内推工作学长学姐在互联网大厂蹲坑直接甩岗位链接。咱这毕业设计要是成了答辩老师看了都得夸“这学生有点东西” 赶紧加群一起卷死同学顺便搞钱PS群里还有人分享“如何用AI写论文”的玄学技巧亲测能过查重最后求师哥师姐推荐工作福州信息安全行业的岗位求内推鞠躬安装环境PHP:7.2.14调整块大小NOSQLNOSQL不需要任何配置可以直接访问测试SQL创建数据库您可以直接复制脚本进行创建配置数据库连接安装依赖访问页面进行测试数据表中的数据效果预览文件上传文件刷新续传支持离线保存文件进度在关闭浏览器刷新浏览器后进行不丢失仍然能够继续上传文件夹上传支持上传文件夹并保留层级结构同样支持进度信息离线保存刷新页面关闭页面重启系统不丢失上传进度。免费下载示例点击下载完整示例