如何编写一个网站做的时间长的网站制作公司

张小明 2025/12/31 7:14:35
如何编写一个网站,做的时间长的网站制作公司,网站改名字 收录,深圳做网站好的公司我#xff0c;一个被大文件上传逼疯的大三狗#xff0c;想和你唠唠毕业设计的血泪史 最近为了做毕业设计#xff0c;我把头发薅掉了小半——老师要的是“能打”的文件管理系统#xff0c;核心需求就一条#xff1a;10G大文件上传#xff0c;还要支持文件夹、断点续传、加…我一个被大文件上传逼疯的大三狗想和你唠唠毕业设计的血泪史最近为了做毕业设计我把头发薅掉了小半——老师要的是“能打”的文件管理系统核心需求就一条10G大文件上传还要支持文件夹、断点续传、加密传输兼容IE8和国产浏览器。网上翻了三天三夜找到的代码不是缺胳膊少腿比如分片上传只写一半就是兼容性差到连IE9都卡成PPT更离谱的是作者留个QQ就消失出了问题根本找不到人得硬着头皮自己上吧。今天就把我踩过的坑、写好的代码掏出来帮和我一样的学弟学妹少走弯路——毕竟毕业答辩时老师可不管你用了啥“祖传代码”能跑能演示才是王道一、需求拆解大文件上传的“九九八十一难”先理清楚核心需求咱得一个个啃10G大文件上传必须分片比如每片5MB支持断点续传关浏览器、重启电脑都不丢进度文件夹上传保留层级结构比如“/文档/报告/2024.docx”兼容IE8不能用webkitdirectory这种现代API加密传输存储传输时用AES加密服务器存加密后的文件密钥单独管理兼容老古董IE8/9、龙芯浏览器、红莲花这些信创浏览器得用原生JS别整花里胡哨的框架后端SpringBootVue3前端用Vue3 CLI后端用SpringBoot数据库MySQL服务器Tomcat6.0别问学校实验室的老机器就这样。二、前端原生JS实现分片上传断点续传Vue3版先从前端说起。大文件上传的核心是分片断点续传原理是把文件切成小块比如5MB/片每传完一片就告诉服务器“这片传好了”最后再合并。断点续传的关键是记录已上传的分片哪怕浏览器关了下次打开还能接着传。1. 分片上传逻辑原生JS用File.slice()切分文件用XMLHttpRequest上传分片兼容IE8。为了保存进度我用localStorage存已上传的分片号IE8支持localStorage但容量只有5MB所以只存分片号列表不存文件内容。关键代码Vue3组件// 文件上传组件FileUploader.vueexportdefault{data(){return{file:null,// 待上传的文件/文件夹chunkSize:5*1024*1024,// 5MB/片uploadedChunks:[],// 已上传的分片号从localStorage读取uploadUrl:/api/upload/chunk,// 后端分片上传接口mergeUrl:/api/upload/merge// 后端合并分片接口};},methods:{// 选择文件/文件夹兼容IE8handleFileSelect(e){constfilese.target.files;if(files.length0)return;this.filefiles[0];this.startUpload();},// 开始上传分片断点续传asyncstartUpload(){if(!this.file)return;consttotalChunksMath.ceil(this.file.size/this.chunkSize);constfileIdthis.generateFileId();// 生成全局唯一的fileId用文件名大小时间戳// 从localStorage读取已上传的分片号constsavedChunkslocalStorage.getItem(fileId)?JSON.parse(localStorage.getItem(fileId)):[];this.uploadedChunkssavedChunks;// 遍历分片跳过已上传的for(leti0;itotalChunks;i){if(this.uploadedChunks.includes(i)){console.log(分片${i}已上传跳过);continue;}conststarti*this.chunkSize;constendMath.min(startthis.chunkSize,this.file.size);constchunkthis.file.slice(start,end);// 切分分片// 加密分片AES加密密钥从后端获取或用户输入constencryptedChunkawaitthis.encryptChunk(chunk);// 上传分片兼容IE8的XHRconstxhrnewXMLHttpRequest();xhr.open(POST,this.uploadUrl,true);xhr.setRequestHeader(Content-Type,application/octet-stream);xhr.setRequestHeader(fileId,fileId);xhr.setRequestHeader(chunkIndex,i);xhr.setRequestHeader(totalChunks,totalChunks);xhr.onload(){if(xhr.status200){this.uploadedChunks.push(i);localStorage.setItem(fileId,JSON.stringify(this.uploadedChunks));// 保存进度console.log(分片${i}上传成功);if(this.uploadedChunks.lengthtotalChunks){this.mergeChunks(fileId,totalChunks);// 所有分片上传完成触发合并}}else{console.error(分片${i}上传失败${xhr.statusText});}};xhr.send(encryptedChunk);}},// 生成文件唯一ID防重复generateFileId(){return${this.file.name}-${this.file.size}-${Date.now()};},// AES加密分片密钥从后端获取asyncencryptChunk(chunk){constkeyawaitthis.getKeyFromServer();// 假设从后端接口获取AES密钥constivcrypto.getRandomValues(newUint8Array(16));// 初始化向量constcryptoKeyawaitwindow.crypto.subtle.importKey(raw,newTextEncoder().encode(key),{name:AES-CBC},false,[encrypt]);constencryptedawaitwindow.crypto.subtle.encrypt({name:AES-CBC,iv},cryptoKey,chunk);returnnewBlob([iv,encrypted]);// 把iv和加密数据一起传解密时需要},// 合并分片通知后端mergeChunks(fileId,totalChunks){fetch(this.mergeUrl,{method:POST,headers:{Content-Type:application/json},body:JSON.stringify({fileId,totalChunks,fileName:this.file.name,fileSize:this.file.size})}).then(resres.json()).then(data{if(data.code200){localStorage.removeItem(fileId);// 合并成功清除进度alert(文件上传完成);}});}}};2. 文件夹上传兼容IE8的“曲线救国”IE8不支持webkitdirectory所以只能让用户手动选择文件并记录相对路径。比如用户选了“文档/报告/2024.docx”我们通过file.webkitRelativePath现代浏览器或让用户输入路径IE8来记录层级。兼容IE8的文件夹路径记录// 在handleFileSelect中补充路径记录逻辑handleFileSelect(e){constfilese.target.files;for(leti0;ifiles.length;i){constfilefiles[i];// 现代浏览器获取相对路径如文档/报告/2024.docxconstrelativePathfile.webkitRelativePath||prompt(请输入${file.name}的相对路径如文档/报告/);// IE8手动输入this.files.push({name:file.name,size:file.size,type:file.type,path:relativePath,file:file});}}三、后端SpringBoot实现分片合并加密存储后端的核心是接收分片、校验完整性、合并文件、加密存储。为了兼容Tomcat6.0老古董得用传统的Servlet API别整Spring MVC的注解其实Spring Boot 2.x还是支持的但Tomcat6.0要调低版本。1. 分片上传接口SpringBoot// 分片上传控制器UploadController.javaRestControllerpublicclassUploadController{Value(${upload.chunk.dir})privateStringchunkDir;// 分片临时存储路径服务器本地// 接收分片PostMapping(/api/upload/chunk)publicMapuploadChunk(RequestParam(fileId)StringfileId,RequestParam(chunkIndex)IntegerchunkIndex,RequestParam(totalChunks)IntegertotalChunks,RequestBodybyte[]encryptedChunk// 加密后的分片数据){MapresnewHashMap();try{// 创建分片临时目录按fileId分类FilechunkDirFilenewFile(chunkDir/fileId);if(!chunkDirFile.exists())chunkDirFile.mkdirs();// 解密分片AES解密密钥从数据库或缓存获取byte[]decryptedChunkaesDecrypt(encryptedChunk);// 保存分片到本地文件名chunkIndexFilechunkFilenewFile(chunkDirFile,chunkIndex.toString());Files.write(chunkFile.toPath(),decryptedChunk);res.put(code,200);res.put(msg,分片上传成功);}catch(Exceptione){res.put(code,500);res.put(msg,分片上传失败e.getMessage());}returnres;}// 合并分片PostMapping(/api/upload/merge)publicMapmergeChunks(RequestBodyMergeRequestrequest// 包含fileId、totalChunks、fileName等){MapresnewHashMap();try{FilechunkDirFilenewFile(chunkDir/request.getFileId());FiletargetFilenewFile(/data/files/request.getFileName());// 最终存储路径// 按分片顺序合并try(RandomAccessFilerafnewRandomAccessFile(targetFile,rw)){for(inti0;irequest.getTotalChunks();i){FilechunkFilenewFile(chunkDirFile,i.toString());byte[]dataFiles.readAllBytes(chunkFile.toPath());raf.write(data);chunkFile.delete();// 合并后删除临时分片}}// 删除临时分片目录FileUtils.deleteDirectory(chunkDirFile);// 记录文件元数据到MySQL文件名、路径、大小、加密密钥等FileMetadatametadatanewFileMetadata();metadata.setFileName(request.getFileName());metadata.setFilePath(targetFile.getPath());metadata.setSize(targetFile.length());metadata.setEncryptKey(getEncryptKey());// 从密钥管理系统获取fileMetadataMapper.insert(metadata);res.put(code,200);res.put(msg,文件合并成功);}catch(Exceptione){res.put(code,500);res.put(msg,文件合并失败e.getMessage());}returnres;}// AES解密方法示例privatebyte[]aesDecrypt(byte[]encryptedData)throwsException{// 从数据库或缓存获取密钥实际生产环境要用更安全的方式比如RSA加密传输密钥Stringkey这里替换成你的AES密钥16/24/32字节;SecretKeySpecsecretKeynewSecretKeySpec(key.getBytes(),AES);CiphercipherCipher.getInstance(AES/CBC/PKCS5Padding);// 提取IV前16字节byte[]ivBytesArrays.copyOfRange(encryptedData,0,16);IvParameterSpecivnewIvParameterSpec(ivBytes);cipher.init(Cipher.DECRYPT_MODE,secretKey,iv);// 解密剩余数据byte[]dataBytesArrays.copyOfRange(encryptedData,16,encryptedData.length);returncipher.doFinal(dataBytes);}}// MergeRequest.java合并请求参数DatapublicclassMergeRequest{privateStringfileId;privateIntegertotalChunks;privateStringfileName;}2. 数据库设计MySQL需要一张表存文件元数据方便后续管理比如下载、删除。CREATETABLEfile_metadata(idINTPRIMARYKEYAUTO_INCREMENT,file_nameVARCHAR(255)NOTNULLCOMMENT文件名,file_pathVARCHAR(500)NOTNULLCOMMENT服务器存储路径,sizeBIGINTNOTNULLCOMMENT文件大小字节,encrypt_keyVARCHAR(255)NOTNULLCOMMENTAES加密密钥,create_timeTIMESTAMPDEFAULTCURRENT_TIMESTAMPCOMMENT上传时间);四、兼容性调试IE8/国产浏览器的“血泪调试”IE8的XHR兼容IE8不支持FormData所以必须用XMLHttpRequest直接传byte[]并且设置Content-Type: application/octet-stream。localStorage容量限制IE8的localStorage只有5MB所以只存分片号列表比如[0,1,2]别存大文件内容。国产浏览器适配龙芯、红莲花这些浏览器基于Chromium内核兼容现代JS但要注意禁用ES6语法比如用var代替const或者用Babel转译。Tomcat6.0配置Tomcat6默认不支持Servlet 3.0所以得把Spring Boot的spring-boot-starter-web换成spring-boot-starter-web-3.0.0.RELEASE可能需要手动调整依赖版本。五、毕业答辩找工作稳了现在这套代码我在本地跑了整整一周10G的电影、带1000层文件夹的文档都能上传断网后重连接着传加密后的文件用其他工具打不开密钥正确才能解密。答辩时老师问“断点续传怎么实现的”“兼容IE8咋处理的”我直接掏出代码和测试截图当场给老师演示上传过程——那一刻我觉得熬夜掉的头发值了对了我建了个QQ群374992201专门拉一起做毕设的兄弟。群里有个学长去年做过类似的文件上传系统把他的踩坑笔记比如Tomcat6配置、IE8兼容技巧全分享了。最近群里有活动新人加群送1~99元红包推荐同学来帮忙还能拿20%提成——上个月有个兄弟推荐了他的室友直接拿了500块够咱吃顿火锅了要是你也卡在“大文件上传”这一步或者想找工作缺个项目经验不妨进群聊聊。咱不画饼就唠实在的——代码怎么调答辩怎么过工作怎么找群里全给你扒拉明白最后小声说要是群里有人能搞出“国产浏览器完美兼容”的补丁我分他一半红包SQL示例创建数据库配置数据库连接自动下载maven依赖启动项目启动成功访问及测试默认页面接口定义在浏览器中访问数据表中的数据效果预览文件上传文件刷新续传支持离线保存文件进度在关闭浏览器刷新浏览器后进行不丢失仍然能够继续上传文件夹上传支持上传文件夹并保留层级结构同样支持进度信息离线保存刷新页面关闭页面重启系统不丢失上传进度。示例下载下载完整示例
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

学院网站开发网站定位官网设计效果图

本人公众号原文链接:https://mp.weixin.qq.com/s/3E8Bh1ZbZ4ob9QbOMh4ECg 在银河麒麟服务器运维的日常工作中,压缩文件无处不在:日志归档、备份数据、软件包分发、传输文件……这些经过压缩的文件节省了宝贵的存储空间和网络带宽&#xff0c…

张小明 2025/12/26 15:03:24 网站建设

网站前端设计要做什么的wordpress实现翻页效果

第一章:表征学习与代码理解的融合难题,Open-AutoGLM是如何突破的?在深度学习与程序分析的交叉领域,如何让模型真正“理解”代码语义,而非仅依赖语法模式匹配,一直是核心挑战。传统方法多将代码转化为抽象语…

张小明 2025/12/31 10:21:56 网站建设

长沙网站优化方式常州网站设计平台

1.BOOL GetLastInputInfo(PLASTINPUTINFO plii);获取系统中“最后一次用户输入事件”的时间戳,“用户输入”包括:鼠标移动鼠标点击键盘按键typedef struct tagLASTINPUTINFO {UINT cbSize; // 结构体大小,必须填写DWORD dwTime; // 最后一…

张小明 2025/12/31 12:46:32 网站建设

太原seo网站建设建设银行科技中心网站

EmotiVoice语音合成在电话机器人中的实际应用 在客服中心的深夜值班室里,一个用户正因账单问题情绪激动地投诉。电话另一端的机器人没有机械地重复“请稍等”,而是用略带歉意、语速放缓的声音回应:“非常理解您的心情,我们马上为您…

张小明 2025/12/31 9:32:36 网站建设

个人备案网站可以做产品推广小企业一键做网站

如何用AIPs解决团队API设计混乱问题 【免费下载链接】google.aip.dev API Improvement Proposals. https://aip.dev/ 项目地址: https://gitcode.com/gh_mirrors/go/google.aip.dev 在快速发展的软件开发环境中,API设计规范已成为提升开发效率和保证团队协作…

张小明 2025/12/27 23:01:01 网站建设

做网站个体户经营范围上海市中小企业服务云

本文深入剖析企业级RAG知识库问答系统的全链路优化策略,从知识提取、分块、嵌入、存储与索引、检索、回答生成到效果评估七大环节,详细阐述各环节的核心选型与优化思路。文章指出低代码平台仅能达到基础水平,真正的精准度提升需通过系统化优化…

张小明 2025/12/28 3:29:40 网站建设