C++毕业设计实战:用SFML开发青蛙过河游戏
2026/10/7 5:42:12
兄弟,作为山西某高校软工专业的大三老狗,我太懂你现在的处境了——毕业设计要做文件管理系统,甲方(老师)要10G大文件上传、加密、断点续传,还要兼容IE8和信创浏览器;找工作要作品,网上找的代码全是“断头路”,出了问题连个问的人都没有。别慌!我熬了三个月啃下的原生JS+SpringBoot全栈方案,今天全盘托出,保证你能直接拿给老师演示,答辩时被夸“这届学生有点东西”!
/文件夹/子文件路径存储(IE8用“伪路径+元数据”方案兜底)。crypto-js(AES)+spark-md5(文件哈希),代码直接嵌入Vue3项目。import { ref, onMounted } from 'vue'; import SparkMD5 from 'spark-md5'; import CryptoJS from 'crypto-js'; import axios from 'axios'; const fileInput = ref(null); const uploadTasks = ref([]); const chunkSize = 5 * 1024 * 1024; // 5MB分片(兼容IE8内存) let aesKey = ''; // AES密钥(从后端动态获取) let currentTaskId = ''; // 上传下一个分片(递归) const uploadNextChunk = (task) => { if (task.chunkIndex >= task.totalChunks) { task.progress = 100; task.status = 'success'; task.statusText = '上传成功'; localStorage.removeItem(`upload_${task.taskId}`); ElMessage.success(`${task.fileName} 上传完成!`); return; } const start = task.chunkIndex * chunkSize; const end = Math.min(start + chunkSize, task.totalSize); const chunk = task.file.slice(start, end); // IE8支持File.slice // 3. 读取分片内容并加密(原生JS) const reader = new FileReader(); reader.onload = (function(chunk, task) { return function(e) { const chunkContent = e.target.result; // AES加密(兼容IE8的crypto-js) const encryptedChunk = CryptoJS.AES.encrypt( CryptoJS.lib.WordArray.create(chunkContent), aesKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 } ).toString(); // 4. 构造FormData(兼容IE8) const formData = new FormData(); formData.append('taskId', task.taskId); formData.append('chunkIndex', task.chunkIndex); formData.append('totalChunks', task.totalChunks); formData.append('filePath', task.filePath); formData.append('chunk', new Blob([encryptedChunk])); // 5. 调用后端上传接口(SpringBoot) axios.post('/api/upload/chunk', formData, { headers: { 'Content-Type': 'multipart/form-data' }, onUploadProgress: (e) => { if (e.lengthComputable) { const speed = (e.loaded - task.uploadedSize) / (e.timeStamp - (task.lastTime || Date.now())) / 1024; task.speed = speed.toFixed(2); task.lastTime = e.timeStamp; } } }).then((res) => { // 6. 更新进度并继续下一个分片 task.chunkIndex++; task.uploadedSize += chunk.size; task.progress = Math.round((task.uploadedSize / task.totalSize) * 100); task.status = 'uploading'; task.statusText = '上传中...'; uploadNextChunk(task); }).catch((err) => { task.status = 'failed'; task.statusText = `上传失败:${err.response?.data?.msg || '网络错误'}`; }); }; })(chunk, task); reader.readAsArrayBuffer(chunk); }; onMounted(() => { initAesKey(); checkResumeTasks(); });// com.example.uploader.service.UploadService.java@Service@Slf4jpublicclassUploadService{@Value("${upload.chunk.size:5242880}")// 5MB分片privatelongchunkSize;@Value("${oss.access.key:your-access-key}")privateStringossAccessKey;@Value("${oss.secret.key:your-secret-key}")privateStringossSecretKey;@Value("${oss.bucket.name:your-bucket}")privateStringossBucket;@AutowiredprivateUploadProgressMapperprogressMapper;// MyBatis Mapper(MySQL)// 上传分片(支持断点续传)publicvoiduploadChunk(UploadChunkDTOchunkDTO,MultipartFilechunk)throwsIOException{// 1. 校验分片有效性(文件指纹+签名)StringfileHash=calculateFileHash(chunkDTO.getFileId(),chunk.getSize());if(!validateChunkSignature(chunkDTO,fileHash)){thrownewSecurityException("分片签名验证失败");}// 2. 解密分片(AES-256)byte[]decryptedChunk=aesDecrypt(chunk.getBytes(),chunkDTO.getUploadToken());// 3. 保存分片到OSS(支持公有云/私有云)StringossPath=getOssPath(chunkDTO.getFilePath(),chunkDTO.getChunkIndex());ossClient.putObject(ossBucket,ossPath,newByteArrayInputStream(decryptedChunk));// 4. 记录进度到MySQL(断点续传关键)UploadProgressprogress=buildProgress(chunkDTO);progressMapper.insertOrUpdate(progress);// MyBatis动态SQL(兼容MySQL)}}-- 创建上传进度表(记录分片上传状态)CREATETABLEIFNOTEXISTSupload_progress(idINTUNSIGNEDAUTO_INCREMENTPRIMARYKEY,task_idVARCHAR(255)NOTNULLCOMMENT'任务ID',file_idVARCHAR(255)NOTNULLCOMMENT'文件唯一ID',chunk_indexINTNOTNULLCOMMENT'当前分片索引',total_chunksINTNOTNULLCOMMENT'总分片数',file_pathVARCHAR(1000)NOTNULLCOMMENT'文件存储路径',uploaded_sizeBIGINTNOTNULLCOMMENT'已上传大小',statusVARCHAR(50)NOTNULLDEFAULT'pending'COMMENT'状态(pending/resuming/uploading/failed/success)',create_timeTIMESTAMPDEFAULTCURRENT_TIMESTAMP,update_timeTIMESTAMPDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,UNIQUEKEYuk_task_file(task_id,file_id,chunk_index)-- 防止重复记录)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;File.slice,需引入Blob.js补丁(https://github.com/eligrey/Blob.js)。FormData,需用iframe模拟上传(代码中已处理)。localStorage容量限制为5MB,大文件进度需分块存储(代码中已拆分)。font-family: "宋体", sans-serif;。*通配符测试)。毕业设计是敲门砖:这个大文件上传项目覆盖了“分布式存储”“加密算法”“浏览器兼容”三大核心技术,答辩时重点讲断点续传的实现逻辑和加密存储的安全性设计,老师一定眼前一亮。
群里的资源别浪费:QQ群(374992201)里有200+软工/计算机专业的学长学姐,有内推机会、面试题库、实习信息,我上周刚通过群里拿到了某国企的实习offer!
简历突出项目:把“10G大文件上传”“加密传输”“兼容IE8”写进简历,面试官最吃“解决实际问题”的候选人。
兄弟,这套代码你拿去练手,保证答辩时老师竖大拇指!有问题直接甩日志到群里,老狗我24小时在线帮你改。毕业前记得加群(374992201)领红包,顺便找个好工作——咱软工学子,不能输!
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。
下载完整示例