当前位置: 首页 > news >正文

湖北网站建设详细方案网络优化app

湖北网站建设详细方案,网络优化app,私人网站如何做竞价,加强网站安全建设方案文章目录 一、原理分析1.1 文件分片1.2 断点续传和断点下载1.2 文件分片下载的 HTTP 参数 二、文件上传功能实现2.1 客户端(前端)2.2 服务端 三、文件下载功能实现3.1 客户端(前端)3.2 服务端 四、功能测试4.1 文件上传功能测试4.2 文件下载功能实现 参考资料 完整案例代码java-demos/spring-boot-demos/spring-boot-file at main · idealzouhu/java-demos (github.com) 一、原理分析 断点上传和下载通常需要支持文件分片。 断点上传上传大文件时支持从上一次中断的位置继续上传。断点下载下载大文件时支持从上一次中断的位置继续下载。 1.1 文件分片 文件分片的核心思想是将服务器上的大文件拆分成若干个小文件等这些小份文件都下载好了之后最后将小文件合并成一个完整的大文件。 以文件分片上传为例客户端责任为 分片 将文件切割成小片。 记录上传进度 记录哪些分片已上传、哪些还未上传。 上传分片 通过 HTTP 请求将每个分片上传到服务端。 服务端责任为 接收分片 将每个分片临时存储。记录已接收分片 记录分片的索引、大小等信息以防止重复上传。文件合并 在所有分片上传完成后将它们合并成完整的文件。 1.2 断点续传和断点下载 断点续传依赖于客户端和服务端的进度记录。 客户端在上传分片时记录当前上传到第几块下一次可以从该分片继续上传。服务端通过每个分片的编号记录已接收的分片检查是否还需要接收未完成的分片。 1.2 文件分片下载的 HTTP 参数 文件分片下载主要依赖于 HTTP 请求头的 Range 参数来实现。 Range 参数用于HTTP请求中允许客户端请求特定字节范围的内容而不是整个资源。这通常用于下载大文件时使得客户端可以实现分块下载、断点续传等功能。 例如客户端只希望获取从200字节到400字节的内容。 GET /path/to/file.txt HTTP/1.1 Host: example.com Range: bytes200-400服务器处理请求并返回一个206 Partial Content响应。 HTTP/1.1 206 Partial Content Content-Range: bytes 200-400/1000 Content-Length: 201 Content-Type: text/plain...这里是文件的第200到400字节的内容...二、文件上传功能实现 在实现文件上传功能中 客户端负责分片上传并记录上传进度服务端负责接收和合并分片。同时本文使用分片编号来实现的并没有使用 range 参数。 2.1 客户端(前端) 创建 fragmentUpload.html 文件具体代码为 !DOCTYPE html html langen headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleFile Chunk Upload/title /head body h2File Chunk Upload with Resume/h2 input typefile idfileInput button onclickuploadFile()Upload/button div idprogress/divscriptconst CHUNK_SIZE 5 * 1024 * 1024; // 1MBlet uploadedChunks 0;async function uploadFile() {const fileInput document.getElementById(fileInput);const file fileInput.files[0];if (!file) {alert(Please select a file!);return;}let totalChunks Math.ceil(file.size / CHUNK_SIZE);while (uploadedChunks totalChunks) {let start uploadedChunks * CHUNK_SIZE;let end Math.min(start CHUNK_SIZE, file.size);let chunk file.slice(start, end);let formData new FormData();formData.append(chunk, chunk);formData.append(fileName, file.name);formData.append(chunkNumber, uploadedChunks 1);formData.append(totalChunks, totalChunks);try {await fetch(/upload-chunk, {method: POST,body: formData});uploadedChunks;document.getElementById(progress).innerText Uploaded chunk ${uploadedChunks} of ${totalChunks};} catch (error) {alert(Upload failed. Retrying...);break;}}} /script /body /html前端通过 File.slice() 方法实现文件分片并逐个上传到服务器。如果上传过程中中断记录上传进度并在恢复时从中断处继续上传。 2.2 服务端 服务端接收分片保存到指定目录并在所有分片上传完成后合并它们。其中每个上传的分片通过 chunkNumber 参数被保存到指定的临时目录中。 RequiredArgsConstructor RestController public class FileChunkUploadController {// 文件临时目录用于保存上传的分片文件private static final String TEMP_DIR D:\\Learning\\temp\\;// 文件上传目录用于保存合并后的文件private static final String UPLOAD_DIR D:\\Learning\\upload\\;/*** 处理单个分片上传请求* p* 当文件较大或网络条件不稳定时客户端可以将文件分割成多个分片分别上传* 这个方法负责接收单个分片并将其保存到临时目录当所有分片上传完成后将它们合并成一个完整的文件* /p** param chunk 分片文件包含文件的一部分* param fileName 原始文件名用于合并分片时命名* param chunkNumber 当前分片的编号从1开始* param totalChunks 总分片数用于判断是否所有分片都已上传* return 分片上传的状态信息* throws IOException 如果文件操作失败*/PostMapping(/upload-chunk)public ResponseEntityString uploadChunk(RequestParam(chunk) MultipartFile chunk,RequestParam(fileName) String fileName,RequestParam(chunkNumber) int chunkNumber,RequestParam(totalChunks) int totalChunks) throws IOException {// 保存分片到临时目录File tempFile new File(TEMP_DIR fileName _ chunkNumber);chunk.transferTo(tempFile);// 检查是否所有分片都已上传if (isAllChunksUploaded(fileName, totalChunks)) {mergeChunks(fileName, totalChunks);}return ResponseEntity.ok(Chunk chunkNumber uploaded);}// 判断是否所有分片都上传完毕private boolean isAllChunksUploaded(String fileName, int totalChunks) {for (int i 1; i totalChunks; i) {File file new File(TEMP_DIR fileName _ i);if (!file.exists()) {return false;}}return true;}// 合并所有分片private void mergeChunks(String fileName, int totalChunks) throws IOException {File mergedFile new File(UPLOAD_DIR fileName);try (FileOutputStream fos new FileOutputStream(mergedFile, true)) {for (int i 1; i totalChunks; i) {File chunkFile new File(TEMP_DIR fileName _ i);try (FileInputStream fis new FileInputStream(chunkFile)) {byte[] buffer new byte[1024];int bytesRead;while ((bytesRead fis.read(buffer)) ! -1) {fos.write(buffer, 0, bytesRead);}}chunkFile.delete(); // 删除分片}}} } 三、文件下载功能实现 在实现文件下载功能中 客户端负责接收分片记录上传进度以及最后的合并分片。服务端负责下载分片。 3.1 客户端(前端) 客户端实现逻辑为 存储所有分片使用 blobParts 数组来存储每个下载的分片的 Blob 对象。 整合分片在所有分片下载完成后使用 new Blob(blobParts) 创建一个完整的 Blob然后生成一个 URL 并触发下载。 触发下载在所有分片下载并整合完后创建一个下载链接并点击它以触发下载。 创建 fragmentDownload.html 文件具体代码为 !DOCTYPE html html langen headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleFile Download with Chunking/titlestylebody {font-family: Arial, sans-serif;}#downloadForm {margin: 20px;}#chunkSize {width: 100px;}#progress {margin-top: 20px;}/style /head body h1File Download with Chunking/h1 div iddownloadFormlabel forfileNameFile Name:/labelinput typetext idfileName placeholderexample.txt requiredbrbrlabel forchunkSizeChunk Size (bytes):/labelinput typenumber idchunkSize value1048576 required !-- 1 MB --brbrbutton iddownloadButtonDownload File/button /div div idprogresspDownload Progress: span idprogressText0/span%/p /divscriptasync function getFileLength(fileName) {const response await fetch(download-chunk?fileName${fileName}, { method: HEAD });const contentLength response.headers.get(content-length);return parseInt(contentLength, 10);}async function downloadFile(fileName, start, end) {const range bytes${start}-${end};const response await fetch(download-chunk?fileName${fileName}, {method: GET,headers: {Range: range,}});if (response.status 206) {return await response.blob(); // 返回 Blob 数据} else {throw new Error(Error: ${response.status});}}async function downloadFileInChunks(fileName, chunkSize) {const fileLength await getFileLength(fileName);let start 0;let end Math.min(chunkSize - 1, fileLength - 1);const totalChunks Math.ceil(fileLength / chunkSize);let downloadedChunks 0;const blobParts []; // 存储所有分片的 Blobwhile (start fileLength) {try {const blob await downloadFile(fileName, start, end);blobParts.push(blob); // 将分片加入数组downloadedChunks;const progressPercentage Math.round((downloadedChunks / totalChunks) * 100);document.getElementById(progressText).innerText progressPercentage;start chunkSize;end Math.min(start chunkSize - 1, fileLength - 1);} catch (error) {console.error(Failed to download chunk: ${error});break;}}// 所有分片下载完成后整合成一个 Blobconst finalBlob new Blob(blobParts);const url URL.createObjectURL(finalBlob);const a document.createElement(a);a.href url;a.download fileName; // 设置下载文件名document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url); // 释放内存if (start fileLength) {alert(Download completed!);}}document.getElementById(downloadButton).onclick function() {const fileName document.getElementById(fileName).value;const chunkSize parseInt(document.getElementById(chunkSize).value);downloadFileInChunks(fileName, chunkSize).catch(console.error);}; /script /body /html在上述代码中 downloadFileInChunks 函数控制文件下载的分片逻辑循环调用 downloadFile 函数进行分片下载。downloadFile 函数执行实际的文件下载请求。其中HTTP 请求设置为 xhr.open(GET, download-chunk?fileName${fileName}, true); 3.2 服务端 服务端主要实现根据 range 参数返回对应的文件分片即可。 RestController public class FileChunkDownloadController {private static final String FILE_DIRECTORY D:\\Program Files\\;// 处理文件下载请求的方法GetMapping(/download-chunk)public ResponseEntityStreamingResponseBody downloadFile(RequestParam String fileName,RequestHeader(value HttpHeaders.RANGE, required false) String range) throws IOException {// 根据文件名构建文件对象File file new File(FILE_DIRECTORY, fileName);if (!file.exists()) {return ResponseEntity.status(HttpStatus.NOT_FOUND).build();}// 获取文件长度, 初始化下载的起始和结束位置long fileLength file.length();long start 0;long end fileLength - 1;// 处理 Range 请求if (range ! null) {// 解析 Range 请求中的起始和结束位置String[] ranges range.replace(bytes, ).split(-);start Long.parseLong(ranges[0]);if (ranges.length 1 !ranges[1].isEmpty()) {end Long.parseLong(ranges[1]);}}// 确保请求的范围合法if (start end || start fileLength) {// 如果请求范围不合法返回 416 REQUESTED RANGE NOT SATISFIABLEreturn ResponseEntity.status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE).header(HttpHeaders.CONTENT_RANGE, bytes */ fileLength).build();}// 如果结束位置超出文件长度调整结束位置if (end fileLength) {end fileLength - 1;}// 设置内容长度long contentLength end - start 1;// 使用 final 关键字定义的变量final long finalStart start;final long finalEnd end;final long finalContentLength contentLength;// 创建 StreamingResponseBody 对象StreamingResponseBody responseBody outputStream - {try (InputStream inputStream new FileInputStream(file)) {inputStream.skip(finalStart); // 跳过起始位置byte[] buffer new byte[1024];int bytesRead;long bytesToRead finalContentLength;while (bytesToRead 0 (bytesRead inputStream.read(buffer, 0, (int) Math.min(buffer.length, bytesToRead))) ! -1) {outputStream.write(buffer, 0, bytesRead);bytesToRead - bytesRead;}} catch (IOException e) {// 打印异常信息e.printStackTrace();}};return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE).header(HttpHeaders.CONTENT_DISPOSITION, attachment; filename\ fileName \).header(HttpHeaders.CONTENT_RANGE, bytes finalStart - finalEnd / fileLength).header(HttpHeaders.ACCEPT_RANGES, bytes).header(HttpHeaders.CONTENT_LENGTH, String.valueOf(finalContentLength)).body(responseBody);} }四、功能测试 4.1 文件上传功能测试 打开客户端 http://localhost:8080/fragmentUpload.html 上传文件。 在测试断点续传的过程中重启服务端然后再次点击客户端前端界面的 Upload 按钮。 4.2 文件下载功能实现 打开客户端 http://localhost:8080/fragmentDownload.html 上传文件 。 不能直接使用 http://localhost:8080/download-chunk?fileNamedemo.txt 来访问会出现问题。 参考资料 实现大文件的断点下载、分片下载 (qq.com)
http://www.dnsts.com.cn/news/149605.html

相关文章:

  • 建一个网站的费用自己做APP需要网站吗
  • 东莞seo网站制作报价广告文案模板
  • 江西省外省建设入库网站建筑方案设计作图题
  • 做网站最烂公司wordpress主题免费
  • 优秀个人博客网站男女做暧视频网站免费
  • 网站排名在线优化工具984网站建设项目
  • wordpress站内私信wordpress右下角设置
  • 营销型网站建ps怎样做网站大图
  • 珠海柏泰教育官方网站建设荣耀手机官方官网
  • 网站开发需求单手机app用什么软件制作
  • 1 设计一个企业网站网站导航做外链
  • 前端代码 分享网站自己做的网站买域名多少钱
  • 东莞seo网站优化郑州推出vip服务
  • 安卓游戏模板下载网站学校网站怎么查询录取
  • 网站开发 竞拍网站岳各庄网站建设
  • 网站icp备案信息网站侧边栏菜单
  • 网页设计企业网站设计的功能vultr 搭建wordpress
  • 高邮建设银行网站绘图软件有哪些
  • 深圳筑造建设有限公司网站沈阳开发网站的地方
  • 杏坛餐饮网站建站中国风网页设计欣赏
  • 北京 网站开发织梦软件展示网站
  • 商丘做网站优化网站优化策略
  • 做p2p网站费用小说网站排名
  • 西安网站建设q.479185700強达州做网站的公司有哪些
  • 优化企业网站模板南昌比较好的网站设计
  • 浦东网站备案流程豌豆荚官网入口
  • 如何做seo整站优化上海中学门户网站
  • 学校网站建设会议讲话稿海南在线人才
  • 为什么网站经常被攻击网络营销名词解释汇总
  • 广州网站建设公司小程序电子商务网站建设期末作业