一个大三狗的文件管理系统历险记
大家好,我是福州某校软件工程专业的大三狗,眼看毕业季来临,我决定做个"惊天地泣鬼神"的文件管理系统当毕业设计(主要是为了找工作时有东西可以吹)。
我的"异想天开"需求清单
- 10G大文件上传:我的笔记本硬盘才512G啊喂!
- 加密传输+存储:这得让我的课程设计看起来像国家安全局项目
- 断点续传:关了浏览器还能接着传?重启电脑也不丢进度?
- 文件夹上传保留结构:还要支持加密传输?(我开始怀疑自己是不是大三学生了)
- 浏览器兼容:从IE8到国产浏览器一个都不能少
- 7*24小时免费技术支持:我自己都天天熬夜改bug,哪来的24小时?
- 免费源代码:毕竟预算=食堂饭卡余额
技术栈迷惑行为
- 前端:Vue3(写着写着就变成jQuery了)
- 后端:SpringBoot(Spring全家桶入门级选手)
- 数据库:MySQL(就会个CRUD)
- 存储:阿里云OSS(因为学生认证有优惠)
- 开发工具:IDEA(唯一用得顺手的)
编码翻车现场
前端部分 (原生JS实现)
// 大文件分片上传(10G?先试试10M吧)classBigFileUploader{constructor(){this.chunkSize=5*1024*1024;// 5MB一片this.retryCount=3;this.queue=[];this.paused=false;}// 选择文件后的处理handleFileSelect(e){constfile=e.target.files[0];if(!file){alert('老板,您倒是选个文件啊!');return;}if(file.size>10*1024*1024*1024){alert('10G?您电脑内存够吗?');return;}this.sliceAndUpload(file);}// 文件分片sliceAndUpload(file){consttotalChunks=Math.ceil(file.size/this.chunkSize);letuploadedChunks=this.loadProgress(file.name)||0;for(leti=uploadedChunks;i<totalChunks;i++){conststart=i*this.chunkSize;constend=Math.min(file.size,start+this.chunkSize);constchunk=file.slice(start,end);this.queue.push({chunk,chunkNumber:i,totalChunks,fileName:file.name,fileSize:file.size,retry:0});}this.processQueue();}// 上传队列处理processQueue(){if(this.paused||this.queue.length===0)return;constitem=this.queue.shift();this.uploadChunk(item).then(()=>{this.saveProgress(item.fileName,item.chunkNumber+1);this.processQueue();}).catch(err=>{console.error('上传失败:',err);if(item.retry<this.retryCount){item.retry++;this.queue.unshift(item);setTimeout(()=>this.processQueue(),1000);}else{alert(`文件${item.fileName}第${item.chunkNumber+1}片上传失败!`);}});}// 实际分片上传uploadChunk(item){returnnewPromise((resolve,reject)=>{constformData=newFormData();formData.append('file',item.chunk);formData.append('chunkNumber',item.chunkNumber);formData.append('totalChunks',item.totalChunks);formData.append('fileName',item.fileName);// 这里应该加上加密逻辑(但我还没学会)constxhr=newXMLHttpRequest();xhr.open('POST','/api/upload',true);xhr.onload=()=>{if(xhr.status===200){resolve(JSON.parse(xhr.responseText));}else{reject(newError('上传失败: '+xhr.statusText));}};xhr.onerror=()=>reject(newError('网络错误'));xhr.send(formData);});}// 保存进度到localStorage(不够持久?)saveProgress(fileName,uploadedChunks){constprogress=JSON.parse(localStorage.getItem('uploadProgress')||'{}');progress[fileName]=uploadedChunks;localStorage.setItem('uploadProgress',JSON.stringify(progress));}// 加载进度loadProgress(fileName){constprogress=JSON.parse(localStorage.getItem('uploadProgress')||'{}');returnprogress[fileName]||0;}}后端部分 (SpringBoot)
@RestController@RequestMapping("/api")publicclassFileUploadController{@Value("${upload.dir}")privateStringuploadDir;@PostMapping("/upload")publicResponseEntityuploadChunk(@RequestParam("file")MultipartFilefile,@RequestParam("chunkNumber")intchunkNumber,@RequestParam("totalChunks")inttotalChunks,@RequestParam("fileName")StringfileName){try{// 创建临时目录StringtempDir=uploadDir+File.separator+"temp_"+fileName;Filedir=newFile(tempDir);if(!dir.exists()){dir.mkdirs();}// 保存分片文件StringchunkName=chunkNumber+".part";FilechunkFile=newFile(dir,chunkName);file.transferTo(chunkFile);// 如果是最后一片,合并文件if(chunkNumber==totalChunks-1){mergeFiles(fileName,tempDir,totalChunks);}returnResponseEntity.ok().body(Map.of("success",true,"message","分片上传成功","chunkNumber",chunkNumber));}catch(Exceptione){returnResponseEntity.status(500).body(Map.of("success",false,"message","分片上传失败: "+e.getMessage()));}}privatevoidmergeFiles(StringfileName,StringtempDir,inttotalChunks)throwsIOException{FileoutputFile=newFile(uploadDir,fileName);try(FileOutputStreamfos=newFileOutputStream(outputFile,true);BufferedOutputStreambos=newBufferedOutputStream(fos)){for(inti=0;i<totalChunks;i++){FilechunkFile=newFile(tempDir,i+".part");try(FileInputStreamfis=newFileInputStream(chunkFile);BufferedInputStreambis=newBufferedInputStream(fis)){byte[]buffer=newbyte[1024];intlen;while((len=bis.read(buffer))>0){bos.write(buffer,0,len);}}chunkFile.delete();// 删除已合并的分片}}// 删除临时目录newFile(tempDir).delete();}}遇到的坑爹问题
- IE8兼容:2023年了还要兼容IE8?我选择放弃治疗!
- 10G文件上传:我的虚拟机内存才分配了4G…
- 断点续传持久化:localStorage根本不够用啊!
- 文件夹结构保持:前端获取不到完整路径,这题超纲了!
- 加密功能:老师教过MD5算吗?(心虚)
我的卑微请求
有没有大神能:
- 教我实现真正的断点续传持久化(IndexedDB?)
- 帮我搞定文件夹结构上传
- 教我简单的文件加密(别太复杂,我怕看不懂)
- 给我的简历加点闪光点(最好能直接帮我写)
欢迎加QQ群374992201交流!新人加群送红包!(虽然可能就1块钱)
毕业答辩生存指南
- 演示时只传小文件(避免当场卡死)
- 重点讲设计思路(代码能跑就行)
- 准备几个专业术语:“分布式存储”、“零信任安全模型”…
- 遇到不会的问题就说"这个功能在下个版本规划中"
找工作求带!
有师兄师姐在招人的吗?我要求不高:
- 能养活自己
- 有电脑用
- 最好不用加班(做梦)
(附上我的专业技能:会Google、会复制粘贴、会重启电脑)
SQL示例
创建数据库
配置数据库连接
自动下载maven依赖
启动项目
启动成功
访问及测试
默认页面接口定义
在浏览器中访问
数据表中的数据
效果预览
文件上传
文件刷新续传
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传
文件夹上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。
示例下载
下载完整示例