JAVA断点续传技术
JAVA大文件上传解决方案(500M以上)
JAVA大文件上传解决方案(500M以上)在Java中,处理大文件上传(500M以上)通常需要注意内存限制和网络传输速度。
以下是一种解决方案,可以帮助您处理这个问题。
2.调整服务器配置:为了支持大文件上传,需要对服务器进行一些配置调整。
例如,增加内存限制以处理大文件的内存需求、将超时时间增加以适应长时间的上传等。
3.分块上传:将大文件分块上传是一种常见的解决方案。
客户端将文件分成多个较小的块,并分批上传到服务器。
在服务器端,通过将这些小块合并成完整的文件来重建原始文件。
4. 上传进度显示:由于大文件可能需要较长时间上传,为了提供更好的用户体验,可以实时显示上传进度。
可以通过监测上传字节数或块数来计算上传进度,并通过AJAX或WebSockets将其在前端显示给用户。
5.断点续传:如果上传过程中发生中断,可以使用断点续传功能让用户从中断点恢复上传。
这可以通过保存已上传的字节或块数并在继续上传时进行验证来实现。
6. 压缩文件:如果可能,可以在客户端将大文件压缩成zip或其他压缩格式。
这将减少文件的大小和上传所需的时间。
7.使用CDN:考虑使用内容分发网络(CDN)来加速文件上传。
CDN可以将文件存储在全球各个服务器上,并将其传输到用户最近的服务器,从而提高上传速度。
8. 文件存储策略:对于大文件,可以将其存储在专门的分布式文件系统中,如Hadoop HDFS或GlusterFS。
这些系统能够处理大型文件的存储和访问,并提供高可用性和容错能力。
9.流式处理:在处理上传文件时,尽量使用流式处理而不是将整个文件加载到内存中。
将输入流与输出流连接,以流式方式传输文件数据,可以最大限度地减少内存消耗。
总结:处理大文件上传的关键是避免将整个文件加载到内存中,并优化上传速度和用户体验。
使用适当的库、合理的服务器配置、分块上传、上传进度显示、断点续传、压缩文件、CDN等策略可以有效解决这个问题。
此外,合理选择文件存储策略和使用流式处理也是很重要的。
java实现文件切片上传百度云+断点续传的方法
java实现⽂件切⽚上传百度云+断点续传的⽅法前⾔:本⽂代码通过dubbo进⾏远程调⽤的接⼝,如果不使⽤dubbo,直接将service放到你的service,并稍作修改,redis替换成⾃⼰封装的⼯具即可。
下⽅代码有点多,但基本上都加注释了。
切⽚上传百度云和上传到本地有所不同,上传到本地是需要前端给个唯⼀标识,通过⾃定义唯⼀标识保存到本地,最后在合并⽂件。
⽽上传百度云则需要直接把切⽚传到百度云,唯⼀标识uploadId是百度云提供的,上传及合并都是直接调⽤百度云提供的接⼝。
下⽅为百度云的使⽤⽂档。
1.定义⼀个实体类⽤于接收前台传过来的信息,信息应该包括总切⽚数,当前切⽚数,⽂件名称,⽂件总⼤⼩。
import mon.annotation.Excel;import lombok.Data;import javax.validation.constraints.Max;import javax.validation.constraints.Min;import javax.validation.constraints.NotNull;import java.io.Serializable;@Datapublic class MutilFileInfo implements Serializable {private static final long serialVersionUID = 1L;@NotNull(message = "车型不能为空")@Excel(name = "车型")private String model;@Excel(name = "⽂件名称")private String name;@Excel(name = "⽂件总⼤⼩")private Long totalSize;@Min(value = 1, message = "不能⼩于1")@Max(value = 10000, message = "不能⼤于10000")@Excel(name = "当前分⽚序号")private Integer chunk;@Min(value = 1, message = "不能⼩于1")@Max(value = 10000, message = "不能⼤于10000")@Excel(name = "分⽚总数")private Integer chunks;}2.创建controller⽤于处理前端过来的⽂件及信息import com.alibaba.fastjson.JSON;import com.baidubce.services.bos.model.PartETag;import mon.annotation.Log;import mon.bean.MutilFileInfo;import mon.bean.baidu.CustomPartETag;import mon.bean.measure.Cmm3dModel;import mon.configuration.RedisUtils;import mon.enums.BusinessType;import mon.util.StringUtils;import com.geely.tcom.remote.api.baidu.BaiduCloudBosService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import java.util.*;import java.util.concurrent.Semaphore;import java.util.stream.Collectors;@Api(tags = "⽂件上传下载服务")@RequestMapping("/threeModel")@RestController@Slf4jpublic class Model3DController1 {//DubboReference这个是远程调⽤,如果没有远程调⽤,直接Autowired就可以@DubboReference(version = "${sheet.service.version}")private BaiduCloudBosService baiduCloudBosService;//通过加锁保证线程安全private Semaphore lock = new Semaphore(1);//api开头的这些是swagger⽤到的,如果没使⽤swagger可以删到PostMapping上边@ApiOperation(value = "obj模型上传")@ApiImplicitParams({@ApiImplicitParam(name = "totalSize", value = "⽂件总⼤⼩",dataTypeClass = Long.class),@ApiImplicitParam(name = "chunks", value = "总切⽚数",dataTypeClass = Integer.class),@ApiImplicitParam(name = "chunk", value = "当前切⽚数",dataTypeClass = Integer.class),@ApiImplicitParam(name = "model", value = "车型",dataTypeClass = String.class),@ApiImplicitParam(name = "file", value = "切⽚⽂件",dataTypeClass = MultipartFile.class)})@Log(title = "obj模型上传", businessType = BusinessType.INSERT)@PostMapping("/upload3DToBos")public Object upload3DToBos( MutilFileInfo fileinfo, @RequestParam(required=false,value="file") MultipartFile multipartFile) {String model=fileinfo.getModel().trim();Map<String,Object> m=new HashMap();String fileName=fileinfo.getName();if (StringUtils.isEmpty(fileName)) {//判断⽂件名称是否为空m.put("key","error");m.put("value","⽂件名不能为空");return m;}if (multipartFile == null) {//判断上传过来的切⽚是否为空m.put("key","error");m.put("value","请上传⽂件");return m;}try{String filePath="/test/"+model+"/"+fileName;//拼接百度云地址String redisKey="partETags-"+model+"-"+fileName;//缓存的键Integer current =fileinfo.getChunk();//当前切⽚数Integer total = fileinfo.getChunks();//总切⽚数Long size=multipartFile.getSize();//⽂件⼤⼩String uploadId = getUploadId(redisKey, filePath);//该⽅法获取百度云的唯⼀标识uploadIdbyte[] file = multipartFile.getBytes();//将切⽚过来的⽂件转成字节数组if(current==1){//这块进⾏断点续传,如果是第⼀个切⽚,查询⼀下缓存中是否有数据了,如果有返回给前台,如果没有进⾏上传if(getCurrentEqualsOne(redisKey).size()>0) {//给前台提供是否缓存中已有数据return getCurrentEqualsOne(redisKey);}}//切⽚上传百度云List<CustomPartETag> customPartETags = getPartEtags(redisKey, uploadId, filePath, file, size, current);//如果缓存中成功的切⽚数等于总数,那么进⾏合并if (customPartETags.size() == total) {customPartETags = customPartETags.stream().sorted(paring(PartETag::getPartNumber)).collect(Collectors.toList());//进⾏排序pletePart(uploadId, customPartETags, filePath);//执⾏合并RedisUtils.hdel(redisKey,"uploadId","customPartETags");//如果合并成功,删除缓存中的数据// ⼊库做记录m.put("key","success");m.put("value","上传成功");return m;}m.put("key","continue");m.put("value",current+1);return m;}catch (Exception e){e.printStackTrace();m.put("key","error");m.put("value","上传失败");return m;}}/*** 获取 part** @param redisPartKey redisKey* @return*/private List<CustomPartETag> getPartEtags(String redisPartKey, String uploadId, String filePath, byte[] file, long size, int current) {List<CustomPartETag> customPartETags = null;try {lock.acquire();//因为每次上传成功后都会把成功的切⽚存进百度云,如注解下⽅第四⾏代码,所以每次上传之前需要先取出来,将成功的切⽚放进去customPartETags = RedisUtils.hget(redisPartKey, "customPartETags") == null ? new ArrayList<>() : JSON.parseArray((String) RedisUtils.hget(redisPartKey, "customPartETags"), CustomPartETag.class);//上传百度云成功之后会返回⼀个PartETagg对象,由于项⽬中存在dubbo,顾将CustomPartETag类继承PartETagg进⾏序列化CustomPartETag customPartETag = baiduCloudBosService.uploadCustomPartETag(uploadId, filePath, file, size, current);customPartETags.add(customPartETag);setPartEtagsToRedis(redisPartKey, customPartETags);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.release();}return customPartETags;}/*** 获取 uploadId** @param redisPartKey redisKey* @param filePath filePath* @return*/private String getUploadId(String redisPartKey, String filePath) {String uploadId = null;try {lock.acquire();//线程锁uploadId = (String) RedisUtils.hget(redisPartKey, "uploadId");//先去redis中找,是否已经有uploadIdif (StringUtils.isEmpty(uploadId)) {//判断是否为空,如果为空,说明之前没上传过,为⾸次上传,如果已经存在,返回该uploadIduploadId = baiduCloudBosService.initMultipartUpload(filePath);//进⾏初始化,返回⼀个唯⼀标识uploadIdRedisUtils.hset(redisPartKey, "uploadId", uploadId, 60 * 60);//将返回来的uploadId放到缓存中,下个切⽚上传直接使⽤这个uploadId}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.release();}return uploadId;}/*** 薄墩 partKey到redis** @param redisPartKey* @param customPartETags*/private void setPartEtagsToRedis(String redisPartKey, List<CustomPartETag> customPartETags) {RedisUtils.hset(redisPartKey, "customPartETags", JSON.toJSONString(customPartETags), 60 * 60);}public Map<String,Object> getCurrentEqualsOne(String redisKey){Map<String,Object> m=new HashMap<>();List<CustomPartETag> customPartETags = RedisUtils.hget(redisKey, "customPartETags") == null ? new ArrayList<>() : JSON.parseArray((String) RedisUtils.hget(redisKey, "customPartETags"), CustomPartETag.class); //给前台提供是否缓存中已有数据if(customPartETags.size()==0){return m;}else{//缓存中有数据,返回缓存中数据int t= customPartETags.get(customPartETags.size()-1).getPartNumber();m.put("key","hasValue");m.put("value",t);return m;}}}3.远程的service(如果不⽤远程调⽤,直接创建⼀个service就可以)package com.geely.tcm.sheet.service;import com.baidubce.services.bos.BosClient;import com.baidubce.services.bos.model.*;import mon.bean.baidu.BosResult;import mon.bean.baidu.CustomPartETag;import mon.util.StringUtils;import com.geely.tcom.remote.api.baidu.BaiduCloudBosService;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboService;import org.springframework.beans.factory.annotation.Autowired;import java.io.*;import .URL;import java.util.ArrayList;import java.util.List;/*** 百度私有云服务操作** @author : wangbin* @date : 2021/9/24* @since : 1.0.0*/@Slf4j@DubboService(version = "${sheet.service.version}")public class BaiduCloudBosServiceImpl{@Autowiredprivate BosClient bosClient;public String initMultipartUpload(String filePath) {// 开始Multipart UploadInitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(null, filePath);InitiateMultipartUploadResponse initiateMultipartUploadResponse = bosClient.initiateMultipartUpload(initiateMultipartUploadRequest);// 打印UploadId,它是区分分块上传事件的唯⼀标识String uploadId = initiateMultipartUploadResponse.getUploadId();("filePath= {},uploadId = {}", filePath, uploadId);return uploadId;}public CustomPartETag uploadCustomPartETag(String uploadId, String filePath, byte[] file, long partSize, int partNumber) {UploadPartRequest uploadPartRequest = new UploadPartRequest();uploadPartRequest.setBucketName(null);uploadPartRequest.setKey(filePath);uploadPartRequest.setUploadId(uploadId);InputStream input= new ByteArrayInputStream(file);uploadPartRequest.setInputStream(input);uploadPartRequest.setPartSize(partSize);uploadPartRequest.setPartNumber(partNumber );uploadPartRequest.setMd5Digest("");UploadPartResponse uploadPartResponse = bosClient.uploadPart(uploadPartRequest);PartETag partETag = uploadPartResponse.getPartETag();CustomPartETag customPartETag = new CustomPartETag();customPartETag.setETag(partETag.getETag());customPartETag.setPartNumber(partETag.getPartNumber());return customPartETag;}/*** 分块上传结束之后,当所有的数据Part验证通过后,BOS将把这些数据part组合成⼀个完整的Object** @param uploadId* @param customPartETags* @param filePath*/public void completePart(String uploadId, List<CustomPartETag> customPartETags, String filePath) {//for循环转⼀下 CustomPartETag 转PartETagif(customPartETags.size()>0){List<PartETag> partETags=new ArrayList<>();for(CustomPartETag c:customPartETags){PartETag partETag=new PartETag();partETag.setETag(c.getETag());partETag.setPartNumber(c.getPartNumber());partETags.add(partETag);}CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(null, filePath, uploadId, partETags); CompleteMultipartUploadResponse completeMultipartUploadResponse = pleteMultipartUpload(completeMultipartUploadRequest); ("完成分⽚上传, filePath = {},uploadId = {}, etag = {}", filePath, uploadId,completeMultipartUploadResponse.getETag());}}}4.定义⼀个实体类继承,实现序列化,(dubbo不序列化就会传不过去)import com.baidubce.services.bos.model.PartETag;import java.io.Serializable;public class CustomPartETag extends PartETag implements Serializable {}5.这⾥提供⼀个临时测试的前端代码<html lang="en"><head><meta charset="UTF-8"><title>upload</title><script src="https:///jquery/3.2.1/jquery.min.js"></script></head><body><input type="file" name="file" id="file"><button id="upload" onClick="upload()">upload</button><script type="text/javascript">var bytesPerPiece = 1024 * 1024; // 每个⽂件切⽚⼤⼩定为1MB .var totalPieces;function upload() {var blob = document.getElementById("file").files[0];var start = 0;var end;var index = 1;var filesize = blob.size;var filename = ;//计算⽂件切⽚总数totalPieces = Math.ceil(filesize / bytesPerPiece);while(start < filesize) {end = start + bytesPerPiece;if(end > filesize) {end = filesize;}var chunk = blob.slice(start,end);//切割⽂件var sliceIndex= + index;var formData = new FormData();formData.append("file", chunk, filename);formData.append("totalSize",filesize);formData.append("chunks",totalPieces);formData.append("chunk",index);formData.append("model",'kx11');$.ajax({//路径换成你的路径url: 'http://127.0.0.1:6300/threeModel/upload3DToBos',type: 'POST',dataType:'json',cache: false,data: formData,processData: false,contentType: false,mimeType: "multipart/form-data",success: function (result){console.log(result.value);}});start = end;index++;}}</script></body></html>到此这篇关于java实现⽂件切⽚上传百度云+断点续传的⽅法的⽂章就介绍到这了,更多相关java ⽂件切⽚上传内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
断点续传的原理
Application对象是一个应用程序级的对象,它包含的数据可以在整个Web站点中被所有用户使用,并且可以在网站运行期间持久地保存数据
断点续传的过程
①断点续传需要在下载过程中记录每条线程的下载进度;
②每次下载开始之前先读取数据库,查询是否有未完成的记录,有就继续下载,没有则创建新记录插入数据库;
③在每次向文件中写入数据之后,在数据库中更新下载进度;
④下载完成之后删除数据库中下载记录。
断点续传在HTTP请求上和一般的下载有所不同,客户端浏览器传给Web服务器的时候要多加一条信息——从哪里开始(HTTP请求变量)。要实现HTTP断点续传,Web服务器必须支持HTTP/1.1(相对于HTTP/1.0老版本)。
-解读断点续传的基本原理
断点续传的理解可以分为两部分:一部分是断点,一部分是续传。断点的由来是在下载过程中,将一个下载文件分成了多个部分,同时进行多个部分一起的下载,当某个时间点,任务被暂停了,此时下载暂停的位置就是断点了。续传就是当一个未完成的下载任务再次开始时,会从上次的断点继续传送。
在使用IE下载文件时,遇到网络中断,不需要重新启动机器,也可实现断点续传。前提是,在恢复下载、开始断点续传并提示再次保存文件时,要使用和第一次下载时相同的路径和文件名。
Application与Session对象之间的区别。
1. 应用范围不同。 Session是对应某一个用户的。而Application是整站共用的。
使用多线程断点续传下载的时候,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,多个线程并发可以占用服务器端更多资源,从而加快下载速度。
断点续传的原理范文
断点续传的原理范文断点续传是指在网络传输过程中,如果传输中断或者失败,可以通过记录已经成功传输的部分数据,从上次传输断点处重新开始传输,以达到继续传输的目的。
其原理主要包括断点记录和断点恢复两个部分。
一、断点记录:断点记录是指在传输过程中对已经成功传输的数据进行记录,以便在传输中断后能够准确地知道从哪个位置开始进行断点恢复。
常用的断点记录的方式有两种:1.1文件分块:将文件划分为若干个块或者段,每个块有一个唯一的标识符(如序号),以及该块在文件中的位置信息(如偏移量)。
在传输过程中,记录已经成功传输的块的序号,以及每个块已经传输的字节数。
当传输中断时,根据已经成功传输的块的序号,计算已经传输的字节数,并保存到断点记录文件中。
二、断点恢复:断点恢复是指在传输中断后,通过断点记录来恢复传输的过程。
主要包括如下几个步骤:2.1获取断点记录:在传输中断后,先从断点记录文件中读取已经传输的字节数、块或者段的序号等信息。
2.2 重新建立连接:根据已经传输的字节数,重新建立连接。
可以通过设置HTTP的Range头字段来指定传输的起始位置,也可以通过FTP的REST命令来指定传输的起始位置。
2.3断点续传传输:根据已经传输的字节数,从上次传输的断点处继续传输。
2.4更新断点记录:在传输过程中,实时更新断点记录,记录已经成功传输的字节数,以及块或者段的序号。
当传输完成时,删除断点记录文件。
三、应用场景:断点续传主要用于网络传输过程中对大文件的传输。
由于大文件的传输过程中,网络连通性和稳定性无法保证,传输中断的情况时有发生。
通过断点续传的机制,可以有效提高文件传输的成功率和效率。
2.文件上传:在上传大文件时,如果上传中断,可以通过断点续传机制,从上次传输的断点处重新开始上传,避免重新上传整个文件。
3.P2P文件共享:在P2P文件共享过程中,如果一些传输节点中断,可以通过断点续传机制,从其他节点继续传输。
4.视频直播:在视频直播过程中,如果网络中断,可以通过断点续传机制,从上次传输的断点处继续播放视频。
java的http断点续传原理(二)
java的http断点续传原理(二)//获得文件长度public long getFileSize(){int nFileLength = -1;try{URL url = new URL(siteInfoBean.getSSiteURL());HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection (); httpConnection.setRequestProperty("User-Agent","NetFox");int responseCode=httpConnection.getResponseCode();if(responseCode>=400){processErrorCode(responseCode);return -2; //-2 represent access is error}String sHeader;for(int i=1;;i++){//DataInputStream in = new DataInputStream(httpConnection.getInputStream ()); //Utility.log(in.readLine());sHeader=httpConnection.getHeaderFieldKey(i);if(sHeader!=null){if(sHeader.equals("Content-Length")){nFileLength = Integer.parseInt(httpConnection.getHeaderField(sHeader)); break;}}elsebreak;}}catch(IOException e){e.printStackTrace ();}catch(Exception e){e.printStackTrace ();}Utility.log(nFileLength);return nFileLength;}//保存下载信息(文件指针位置)private void write_nPos(){try{output = new DataOutputStream(new FileOutputStream(tmpFile));output.writeInt(nStartPos.length);for(int i=0;i< p>{// output.writeLong(nPos[i]);output.writeLong(fileSplitterFetch[i].nStartPos);output.writeLong(fileSplitterFetch[i].nEndPos);}output.close();}catch(IOException e){e.printStackTrace ();}catch(Exception e){e.printStackTrace ();}}//读取保存的下载信息(文件指针位置)private void read_nPos(){try{DataInputStream input = new DataInputStream(new FileInputStream(tmpFile)); int nCount = input.readInt();nStartPos = new long[nCount];nEndPos = new long[nCount];for(int i=0;i< p>{nStartPos[i] = input.readLong();nEndPos[i] = input.readLong();}input.close();}catch(IOException e){e.printStackTrace ();}catch(Exception e){e.printStackTrace ();}}private void processErrorCode(int nErrorCode) {System.err.println("Error Code : " + nErrorCode); }//停止文件下载public void siteStop(){bStop = true;for(int i=0;i< p>fileSplitterFetch[i].splitterStop();}}/***FileSplitterFetch.java*/package NetFox;import java.io.*;import .*;public class FileSplitterFetch extends Thread {String sURL; //File URLlong nStartPos; //File Snippet Start Positionlong nEndPos; //File Snippet End Positionint nThreadID; //Thread's IDboolean bDownOver = false; //Downing is overboolean bStop = false; //Stop identicalFileAccessI fileAccessI = null; //File Access interfacepublic FileSplitterFetch(String sURL,String sName,long nStart,long nEnd,int id) throws IOException{this.sURL = sURL;this.nStartPos = nStart;this.nEndPos = nEnd;nThreadID = id;fileAccessI = new FileAccessI(sName,nStartPos);}public void run(){while(nStartPos < nEndPos && !bStop){try{URL url = new URL(sURL);HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection ();httpConnection.setRequestProperty("User-Agent","NetFox");String sProperty = "bytes="+nStartPos+"-";httpConnection.setRequestProperty("RANGE",sProperty);Utility.log(sProperty);InputStream input = httpConnection.getInputStream();//logResponseHead(httpConnection);byte[] b = new byte[1024];int nRead;while((nRead=input.read(b,0,1024)) > 0 && nStartPos < nEndPos && !bStop) {nStartPos += fileAccessI.write(b,0,nRead);//if(nThreadID == 1)// Utility.log("nStartPos = " + nStartPos + ", nEndPos = " + nEndPos); }Utility.log("Thread " + nThreadID + " is over!");bDownOver = true;//nPos = fileAccessI.write (b,0,nRead);}catch(Exception e){e.printStackTrace ();}}}//打印回应的头信息public void logResponseHead(HttpURLConnection con){for(int i=1;;i++){String header=con.getHeaderFieldKey(i);if(header!=null)//responseHeaders.put(header,httpConnection.getHeaderField(header)); Utility.log(header+" : "+con.getHeaderField(header));elsebreak;}}public void splitterStop(){bStop = true;}}/***FileAccess.java*/package NetFox;import java.io.*;public class FileAccessI implements Serializable{ RandomAccessFile oSavedFile;long nPos;public FileAccessI() throws IOException{this("",0);}public FileAccessI(String sName,long nPos) throws IOException {oSavedFile = new RandomAccessFile(sName,"rw");this.nPos = nPos;oSavedFile.seek(nPos);}public synchronized int write(byte[] b,int nStart,int nLen) {int n = -1;try{oSavedFile.write(b,nStart,nLen);n = nLen;}catch(IOException e){e.printStackTrace ();}return n;}}/***SiteInfoBean.java*/package NetFox;public class SiteInfoBean {private String sSiteURL; //Site's URLprivate String sFilePath; //Saved File's Pathprivate String sFileName; //Saved File's Nameprivate int nSplitter; //Count of Splited Downloading Filepublic SiteInfoBean(){//default value of nSplitter is 5this("","","",5);}public SiteInfoBean(String sURL,String sPath,String sName,int nSpiltter) {sSiteURL= sURL;sFilePath = sPath;sFileName = sName;this.nSplitter = nSpiltter;}public String getSSiteURL(){return sSiteURL;}public void setSSiteURL(String value) {sSiteURL = value;}public String getSFilePath(){return sFilePath;}public void setSFilePath(String value) {sFilePath = value;}public String getSFileName(){return sFileName;}public void setSFileName(String value) {sFileName = value;}public int getNSplitter(){return nSplitter;}public void setNSplitter(int nCount) {nSplitter = nCount;}}/***Utility.java*/package NetFox;public class Utility {public Utility(){}public static void sleep(int nSecond) {try{Thread.sleep(nSecond);}catch(Exception e){e.printStackTrace ();}}public static void log(String sMsg){System.err.println(sMsg);}public static void log(int sMsg){System.err.println(sMsg);}}/***TestMethod.java*/package NetFox;public class TestMethod {public TestMethod(){ ///xx/weblogic60b2_win.exetry{SiteInfoBean bean = newSiteInfoBean("http://localhost/xx/weblogic60b2_win.exe","L:\\temp","weblogic60b2_w in.exe",5);//SiteInfoBean bean = newSiteInfoBean("http://localhost:8080/down.zip","L:\\temp","weblogic60b2_win.exe",5) ;SiteFileFetch fileFetch = new SiteFileFetch(bean);fileFetch.start();}catch(Exception e){e.printStackTrace ();}}public static void main(String[] args){new TestMethod();。
断点续传的原理
断点续传的原理断点续传(Resumable Download)是指在文件传输过程中,能够从传输中断的位置继续传输,而不需要重新传输整个文件的技术。
它的实现原理主要涉及到断点记录和范围请求两个方面。
首先,断点记录是指在文件传输过程中记录已经传输的文件片段的大小和位置。
当文件传输被中断时,下一次继续传输时可以通过读取断点记录找到传输的起始位置,并从该位置继续传输。
断点记录可以在客户端或服务端存储,通常使用文件的元数据、特殊文件或数据库记录来保存。
其次,范围请求是指在文件传输过程中,客户端通过发送Range头字段来请求指定文件的某个范围。
服务端收到这个请求后可以根据Range头字段指定的范围将对应的文件内容返回给客户端。
客户端可以在不同时间点多次发送范围请求,以实现断点续传。
断点续传的具体实现可以分为以下几个步骤:1. 客户端发起文件传输请求:客户端向服务端发起文件传输请求,并通过请求头字段Content-Range指定已经传输的文件大小。
如果之前的传输已经被中断,客户端可以通过Content-Range头字段告知服务端已经传输的文件大小。
2. 服务端处理文件传输请求:服务端收到客户端的文件传输请求后,根据请求头字段Content-Range,确定所请求的文件的传输范围。
如果Content-Range 头字段没有提供,服务端可以将整个文件作为范围返回。
然后服务端读取对应范围的文件内容,并通过响应头字段Content-Range来告知客户端返回的文件范围。
3. 客户端接收文件内容:客户端收到服务端返回的文件内容后,将其存储在本地指定的位置,并根据Content-Range响应头字段更新已经传输的文件大小和位置。
如果范围请求仍然没有传输完整个文件,客户端再次发起范围请求来获取剩余的文件内容。
4. 重复步骤2和3:客户端重复执行步骤2和3,直到整个文件传输完成。
每次范围请求都会从上一次传输中断的位置开始继续传输,直到获取全部文件内容。
java断点续传原理与实现
java断点续传原理与实现Java的断点续传是一种实现大文件传输的技术,当传输过程中出现中断或者网络故障时,可以通过断点续传的机制,继续传输文件,而无需重新开始传输。
在传统的文件传输过程中,当文件传输失败时,重新传输整个文件是耗费时间和资源的。
而断点续传则通过记录传输的状态信息,使得在传输中断后可以从断点处继续传输,大大提高了传输效率。
断点续传的实现原理主要涉及到两个方面:状态信息记录和传输的恢复。
首先,要实现断点续传,我们需要记录传输过程的状态信息,包括文件的已传输大小、传输的起始位置等。
可以使用文件的元数据信息或者自定义的记录方式来实现。
这些状态信息通常会储存在服务器或者本地文件系统中。
其次,当传输中断后,需要根据之前记录的状态信息来恢复传输。
在Java中,可以通过读取之前保存的状态信息来确定传输的起始位置,然后从该位置处继续传输。
通过使用Java的文件输入输出流和字节流,可以实现断点续传功能。
具体实现中,可以使用Java的RandomAccessFile类来实现文件的读写操作。
通过设置文件的偏移量,可以从指定位置读取和写入数据。
这样,在断点续传时,我们只需要根据之前记录的起始位置,设置文件的偏移量,即可从断点处继续传输文件。
在实际应用中,我们可以将断点续传功能与HTTP协议结合使用,通过HTTP的Range请求头来实现断点续传功能。
在客户端发送请求时,可以通过设置Range头,指定文件传输的起始位置和结束位置。
服务器在接收到该请求后,根据指定的范围返回相应的文件片段。
这样,当传输中断后,客户端只需要再次发送带有Range头的请求,即可从中断处恢复传输。
总结起来,Java的断点续传通过记录传输状态信息和根据状态信息进行传输的恢复,实现了在传输中断后继续传输文件的功能。
通过合理运用Java的文件操作和网络传输技术,可以实现稳定高效的大文件传输,并在网络传输不稳定的情况下提供了更好的用户体验。
如果想要实现断点续传功能,可以按照上述原理和实现方法进行开发。
断点续传 原理
断点续传原理
断点续传是一种在网络传输过程中,出现中断或失败后能够从断点处继续传输的技术。
其基本原理是通过记录已经传输的部分数据和相关信息,以便在重新连接后能够从断点处继续传输而不是重新开始。
在实现断点续传的过程中,首先需要确保数据的传输能够被分片和编号,这样才能准确地确定断点在哪个位置。
传输开始时,接收端会确认接收到的数据,并将确认信息反馈给发送端。
发送端会根据接收端的确认信息,记录已经成功传输的数据并将剩余未传输的数据继续发送。
当网络连接中断时,断点续传技术能够利用记录的传输数据和相关信息来恢复传输。
当重新连接后,发送端可以根据断点的位置继续发送数据,而不需要从头开始发送。
接收端会根据已经传输的数据进行确认,确保没有丢失或重复的数据。
为了实现断点续传,还需要在发送端和接收端之间进行协调和控制。
发送端需要记录已经传输的数据,并能够根据接收端的反馈信息进行恢复。
接收端则需要能够识别断点的位置并通知发送端从断点处继续传输。
断点续传技术能够提高文件传输的稳定性和效率,特别是在大文件传输或网络不稳定的情况下。
通过减少重新传输的时间和网络开销,断点续传能够显著提升传输的速度和可靠性。
断点续传方案
断点续传方案简介断点续传是指在网络传输过程中,当连接中断或者文件传输中止时,能够从中断处重新开始传输,而不是从头开始。
这样可以提高文件传输的可靠性和传输效率。
在实际应用中,断点续传方案常常用于大文件的上传或下载过程中,以确保用户在网络不稳定的情况下能够顺利完成文件传输,而无需重新开始。
本文将介绍几种常见的断点续传方案,并分析各种方案的优缺点,帮助读者选择适合自己应用场景的方案。
方案一:基于HTTP的断点续传HTTP协议是应用层协议中最常用的协议之一,支持断点续传的HTTP服务器通常会在响应头中添加Range字段,用于指定服务器传输的起始位置。
客户端在进行文件下载时,通过设置请求头中的Range字段来请求指定范围的数据。
服务器接收到请求后,根据Range字段返回相应的数据片段。
如果客户端在下载过程中中断,可以通过设置Range字段重新发送请求,从中断处继续下载。
HTTP的断点续传方案具有以下优点:-:基于HTTP的断点续传方案使用标准的HTTP协议,不需要额外的协议和框架支持,方便快捷。
-:基于HTTP的断点续传方案通常兼容多种操作系统和终端设备,使用广泛。
-:通过设置不同的Range字段,可以实现下载指定范围的数据,具有较高的灵活性。
-:HTTP协议本身就具有较高的可靠性,断点续传方案在一定程度上增强了文件传输的可靠性。
然而,基于HTTP的断点续传方案也存在一些局限性:-:由于每次续传都需要从中断处开始,可能会导致重复传输已经传输过的数据,降低传输效率。
-:对于非常大的文件,服务器需要保存大量的中断点信息,占用较多的磁盘空间和内存资源。
-:如果服务器不支持断点续传,那么即使客户端实现了断点续传方案,也无法成功续传。
方案二:基于FTP的断点续传FTP(File Transfer Protocol)是一种文件传输协议,也常用于文件上传和下载。
FTP支持断点续传的机制,能够在网络中断或传输中止后从中断处继续传输。
java断点续传原理
java断点续传原理断点续传是指在网络传输过程中,当传输中断或失败后,能够从中断处继续传输,而不需要重新开始传输的一种技术。
在Java中实现断点续传主要依赖于HTTP协议和文件流操作。
HTTP协议是一种无连接的协议,每个请求和响应都是独立的。
当客户端发送请求时,服务器会返回一个状态码和文件的相关信息,如果状态码为206,则表示服务器支持部分内容传输,并返回相应的Content-Range头字段,用于指定从哪个字节到哪个字节的内容。
客户端根据这些信息可以知道文件已经传输到哪个位置,从而进行断点续传。
在Java中,可以使用URL类和HttpURLConnection类来实现HTTP连接和文件传输操作。
下面是一个简单的示例代码:```javaimport java.io.*;public class ResumeUploadExamplepublic static void main(String[] args)String savePath = "path/to/save/file";tryURL url = new URL(fileUrl);HttpURLConnection connection = (HttpURLConnection)url.openConnection(;File file = new File(savePath);long startPos = 0;if (file.exists()startPos = file.length(;connection.setRequestProperty("Range", "bytes=" + startPos + "-");}connection.connect(;int responseCode = connection.getResponseCode(;if (responseCode == HttpURLConnection.HTTP_PARTIAL)long contentLength = connection.getContentLengthLong(;InputStream inputStream = connection.getInputStream(;RandomAccessFile outputFile = new RandomAccessFile(file, "rw");outputFile.seek(startPos);byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1)outputFile.write(buffer, 0, bytesRead);}outputFile.close(;inputStream.close(;System.out.println("File downloaded successfully!");} elseSystem.out.println("Server does not support resume!");}} catch (IOException e)e.printStackTrace(;}}```在上述代码中,首先创建URL对象并打开HTTP连接。
java断点续传原理
java断点续传原理Java中的断点续传原理通常用于网络文件传输,即在文件传输过程中,可以在中断或终止的地方继续传输,而无需重新开始传输整个文件。
下面是详细的Java断点续传原理:1.文件分块:要实现断点续传,首先将要传输的文件划分为较小的块或片段。
这样做的目的是在传输过程中,可以只传输所需的文件块,而不必传输整个文件。
2.传输控制:使用网络编程库(如Java的Socket或HttpURLConnection类)在客户端和服务器端之间建立连接,以进行文件传输。
客户端和服务器端之间可以通过交换信息来控制文件的传输。
客户端可以向服务器发送请求,指示从哪个文件块开始传输。
3.传输记录:为了能够在断点处继续传输,需要记录上次传输的位置。
通常使用一个额外的文件或数据库来记录传输的状态。
在每次成功传输一个文件块后,将记录下次需要传输的文件块的位置。
4.传输异常处理:在文件传输过程中,可能会出现网络中断、传输错误或其他异常情况。
当发生这些异常时,客户端和服务器端可以根据传输记录来确定下一个需要传输的文件块,并重新建立连接继续传输。
这样可以避免重新传输已经成功传输的文件块。
5.完成传输:当所有文件块都成功传输并合并到服务器上的完整文件中时,可以认为文件传输已经完成。
可以根据需要在客户端和服务器端进行相应的操作,如关闭连接、进行文件校验等。
当实现Java断点续传时,还可以考虑以下几个方面:1. Range请求:在进行HTTP文件传输时,可以使用Range 请求头来指定从哪个位置开始传输文件。
服务器可以根据Range请求头确定需要传输的文件块范围,然后只传输该范围内的数据。
2. 断点续传请求:在传输中断后,客户端可以向服务器发送断点续传请求,请求从上次传输结束的地方继续传输。
服务器接收到请求后,根据传输记录找到需要传输的下一个文件块,并将其发送给客户端。
3. 文件校验:为了确保文件传输的完整性和准确性,可以在传输过程中进行文件校验。
前端 断点续传 解决方案
前端断点续传解决方案
前端开发中,断点续传是一个常见的需求,特别是在处理大文件上传或下载时。
断点续传是指在传输过程中,当网络中断或传输失败时,能够从中断的地方继续传输,而不需要重新开始。
这在提高用户体验和网络传输效率上都有很大的帮助。
为了实现断点续传,我们可以采用以下几种解决方案之一:
1. 分片上传/下载:将大文件拆分成多个小块,分别进行上传或下载。
每个小块的大小可以根据网络状况和服务器性能进行调整。
在传输过程中,如果网络中断或传输失败,只需要重新传输中断的小块,而不需要重新传输整个文件。
2. 断点续传记录:在传输过程中,记录已经成功传输的部分,以便在传输中断时能够从中断的地方继续传输。
这可以通过在服务器端记录已传输的字节数或文件片段的方式来实现。
当传输中断时,客户端可以通过向服务器发送断点续传请求,服务器会根据记录的信息返回正确的继续传输位置。
3. 并行传输:在传输过程中,可以同时进行多个线程或进程的传输,以提高传输速度和稳定性。
每个线程或进程负责传输文件的不同部分,如果其中一个线程或进程中断,其他线程或进程仍然可以继续传输。
这样可以最大程度地利用网络带宽和服务器性能。
以上是针对前端断点续传的一些常见解决方案。
在实际开发中,可
以根据具体需求选择合适的方案。
同时,还需要考虑网络环境、服务器性能和用户体验等因素,以提供稳定、高效的断点续传功能。
断点续传的原理探讨和编程应用
断点续传的原理探讨和编程应用在服务端,当接收到客户端的传输请求时,根据客户端请求中的起始位置信息确定需要传输的文件的位置。
然后,将文件分割成小块并根据客户端传输的信息恢复已经传输的小块。
服务端将这些已传输的小块发送给客户端,使客户端能够从断点处继续传输。
服务端也需要及时保存已传输的小块的信息,以便出现连接中断后能够从断点处继续传输。
编程实现断点续传可以使用各种编程语言和网络传输协议。
在编程中,需要考虑以下几个方面:1.分割文件:需要将目标文件分割成若干个小块,每个小块包含起始位置和长度信息。
可以使用文件操作的API来实现文件的读取和写入。
2.传输和保存断点信息:在传输过程中,需要及时保存已经传输完成的小块的信息,以便在中断后从断点处恢复传输。
可以使用文件或数据库等方式保存断点信息。
3.连接中断处理:在传输过程中,需要实时检测连接情况。
如果发现连接中断,需要保存已传输的小块信息,并在连接恢复后从断点处继续传输。
4.传输校验:在每个小块传输完成后,需要对传输的数据进行校验,确保数据的准确性。
可以使用校验和、哈希算法等方式进行校验。
5.用户交互和控制:可以提供用户界面或命令行接口来控制断点续传的功能,例如暂停、恢复、取消等操作。
总之,断点续传是一种有效的利用网络传输资源的技术,在各种网络传输应用中都有广泛的应用。
编程实现断点续传需要考虑文件分割、传输和保存断点信息、连接中断处理、传输校验、用户交互等方面。
通过合理的设计和实现,可以实现高效、可靠的断点续传功能。
很简单的Java断点续传实现原理
很简单的Java断点续传实现原理原理解析在开发当中,“断点续传”这种功能很实⽤和常见,听上去也是⽐较有“逼格”的感觉。
所以通常我们都有兴趣去研究研究这种功能是如何实现的?以Java来说,⽹络上也能找到不少关于实现类似功能的资料。
但是呢,⼤多数都是举个Demo然后贴出源码,真正对其实现原理有详细的说明很少。
于是我们在最初接触的时候,很可能就是直接Crtl + C/V代码,然后捣⿎捣⿎,然⽽最终也能把效果弄出来。
但初学时这样做其实很显然是有好有坏的。
好处在于,源码很多,解释很少;如果我们肯下功夫,针对于别⼈贴出的代码⾥那些⾃⼰不明⽩的东西去查资料,去钻研。
最终多半会收获颇丰。
坏处也很明显:作为初学者,⾯对⼀⼤堆的源码,感觉好多东西都很陌⽣,就很容易望⽽⽣畏。
即使最终⼤致了解了⽤法,但也不⼀定明⽩实现原理。
我们今天就⼀起从最基本的⾓度切⼊,来看看所谓的“断点续传”这个东西是不是真的如此“⾼逼格”。
其实在接触⼀件新的“事物”的时候,将它拟化成⼀些我们本⾝⽐较熟悉的事物,来参照和对⽐着学习。
通常会事半功倍。
如果我们刚接触“断点续传”这个概念,肯定很难说清楚个⼀⼆三。
那么,“玩游戏”我们肯定不会陌⽣。
OK,那就假设我们现在有⼀款“通关制的RPG游戏”。
想想我们在玩这类游戏时通常会怎么做?很明显,第⼀天我们浴⾎奋战,⼤杀四⽅,假设终于来到了第四关。
虽然激战正酣,但⼀看墙上的时钟,已经凌晨12点,该睡觉了。
这个时候就很尴尬了,为了能够在下⼀次玩的时候,顺利接轨上我们本次游戏的进度,我们应该怎么办呢?很简单,我们不关掉游戏,直接去睡觉,第⼆天再接着玩呗。
这样是可以,但似乎总觉着有哪⾥让⼈不爽。
那么,这个时候,如果这个游戏有⼀个功能叫做“存档”,就很关键了。
我们直接选择存档,输⼊存档名“第四关”,然后就可以关闭游戏了。
等到下次进⾏游戏时,我们直接找到“第四关”这个存档,然后进⾏读档,就可以接着进⾏游戏了。
这个时候,所谓的“断点续传”就很好理解了。
文件断点续传实现的思路
文件断点续传实现的思路今天的互联网环境中,文件经常需要在网络之间传输,特别是文件大,传输时间长,网络中断。
在这种情况下,最佳解决方案应该是文件断点续传。
断点续传是一种用于安全传输大文件的技术,它能够实现断网情况下的文件传输,解决文件传输过程中出现中断的问题。
断点续传是一种基于TCP/IP协议的文件传输技术,它可以确保传输文件的完整性,避免因断网而中断的传输。
断点续传的实现思路是:当一个文件通过网络发送时,该文件的发送端会先将文件分割成一个个小的片段或块,每一个片段都有其相应的标识符号。
发送端会先发送第一个片段,如果接收端能够收到,接收端就会回复发送端一个接收成功(ACK:Acknowledgment)的确认信息,发送端收到ACK 信息后就会继续发送下一个片段,如果网络中断发送端收不到ACK信息,发送端就会重新发送上一个片段,直到接收端收到了所有片段,完成文件传输。
断点续传也有一些限制条件:文件的大小,网络的带宽和网络的稳定性等。
对于大文件,在断网情况下传输性能很差;网络的带宽也会影响文件的传输性能;而网络稳定性则决定了断网重传次数,如果断网次数过多,也会降低文件传输性能。
因此,应该考虑文件大小、网络带宽、网络稳定性等因素来优化断点续传的效率。
在网络上使用断点续传技术,必须考虑到这些因素,确保断点续传的性能能够达到期望的效果,可以有效的解决文件传输过程中出现的中断问题。
断点续传技术已经在当今的互联网环境中广泛应用,而且由于它的实用性,使用得也越来越广泛。
它既能够确保文件在传输中的完整性,又能缩短文件传输的时间,提高了文件传输的效率,极大地方便了文件传输过程。
总之,断点续传技术可以确保文件传输的完整性,避免因断网而中断的传输,提高文件传输的效率,为当今互联网环境提供了一种可靠的文件传输方案。
JAVA大文件上传解决方案(500M以上)
JAVA大文件上传解决方案(500M以上)要解决Java中的大文件上传问题,需要考虑以下几个方面:上传限制、分片上传、文件合并和断点续传。
下面是一个大文件上传的解决方案,其中包括这些方面的考虑。
1. 上传限制:首先要在服务器端进行上传文件的大小限制,以确保不会超出服务器的处理能力。
可以通过配置文件或者代码来设置最大的上传文件大小。
例如,可以在web.xml文件中添加以下配置:```xml<multipart-config><max-file-size>500MB</max-file-size><max-request-size>500MB</max-request-size></multipart-config>```这样就限制了文件上传的最大大小为500MB。
2. 分片上传:对于大文件,可以将其分割成较小的块进行上传,以避免一次性上传整个文件所带来的内存和网络开销。
在客户端,可以使用JavaScript或者其他前端库来实现文件分片上传。
在服务器端,可以使用Java的输入输出流来逐个接收和保存上传的文件块。
3. 文件合并:在服务器端,需要将上传的文件块进行合并,以还原原始的大文件。
可以使用Java的文件流来将这些文件块按顺序写入到新的文件中。
合并完成后,可以删除上传的文件块。
4.断点续传:为了支持断点续传功能,服务器端需要记录上传文件的状态。
可以使用数据库或者文件系统来保存上传的文件的状态信息,如已上传的文件块以及已完成的文件合并。
这样,当客户端重新上传时,服务器端可以从上次的上传状态开始继续上传。
5.并发上传:大文件上传可能会耗费很长的时间,为了提高上传的效率,可以在服务器端使用多线程或者使用消息中间件来实现并发上传。
多线程可以同时处理多个上传请求,而消息中间件可以将上传任务提交到消息队列中,异步处理上传任务。
总的来说,大文件上传需要在服务器端进行上传限制、分片上传、文件合并和断点续传等处理。
前端开发中的断点续传实现方法
前端开发中的断点续传实现方法在前端开发中,实现断点续传功能是一个常见的需求。
断点续传可以提高文件上传的稳定性和效率,当网络传输中断或者上传时间过长时,可以在上传过程中恢复之前的进度,避免重复上传。
一、断点续传的原理断点续传的原理是将一个大文件分割成多个小块,通过网络分多次上传,每次上传一个小块。
在上传的过程中,服务器会记录已经上传的小块,当上传中断后再次上传时,可以根据已上传的小块进行断点续传。
二、前端实现断点续传的方法1.分块上传首先,前端需要将大文件分割成多个小块,并记录每个小块的状态和上传进度。
在上传的过程中,可以通过监听上传进度事件来获取上传进度。
同时,需要将每个小块的上传状态和进度信息保存在本地,以便在上传中断后可以恢复上传进度。
2.断点续传当上传过程中网络中断或者上传时间过长时,可以通过断点续传功能来恢复上传进度。
前端可以通过向服务器发送请求来查询已上传的小块,服务器返回已上传的小块列表后,前端可以根据已上传的小块进行断点续传。
可以通过判断已上传的小块与分割的小块列表的差异来确定需要继续上传的小块,然后再次发送请求进行上传。
3.进度展示为了方便用户查看上传进度,在前端可以实时展示上传进度。
可以通过监听上传进度事件,获取上传的进度信息,并将其展示在页面上。
可以使用进度条、百分比等形式来展示,提供直观的反馈给用户。
4.异常处理在文件上传的过程中,可能会遇到各种异常情况,比如网络中断、服务器异常等。
前端需要进行相应的异常处理,例如可以提示用户上传失败,提供重新上传或者取消上传的选项。
同时,需要对上传过程中的异常情况进行记录,并提供相应的错误日志,以便后续分析和修复。
三、断点续传的效果和优化通过实现断点续传功能,可以提升文件上传的稳定性和效率。
在网络条件不佳或者文件较大的情况下,断点续传可以避免因上传中断而导致的重复上传。
同时,可以根据已上传的小块情况来判断上传进度,提供更精准的进度展示给用户。
java - 实现断点续传
java实现断点续传(一)断点续传的原理其实断点续传的原理很简单,就是在Http的请求上和一般的下载有所不同而已。
打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:假设服务器域名为,文件名为down.zip。
GET /down.zip HTTP/1.1Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms- Excel, application/msWord, application/vnd.ms-Powerpoint, */*Accept-Language: zh-cnAccept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)Connection: Keep-Alive服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:200Content-Length=106786028Accept-Ranges=bytesDate=Mon, 30 Apr 2001 12:56:11 GMTETag=W/"02ca57e173c11:95b"Content-Type=application/octet-streamServer=Microsoft-IIS/5.0Last-Modified=Mon, 30 Apr 2001 12:56:11 GMT所谓断点续传,也就是要从文件已经下载的地方开始继续下载。
所以在客户端浏览器传给Web服务器的时候要多加一条信息--从哪里开始。
下面是用自己编的一个"浏览器"来传递请求信息给Web服务器,要求从2000070字节开始。
GET /down.zip HTTP/1.0User-Agent: NetFoxRANGE: bytes=2000070-Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2仔细看一下就会发现多了一行RANGE: bytes=2000070-这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。
断点续传原理
断点续传原理断点续传是指在文件传输过程中,当传输中断后,可以从断点处继续传输,而不需要重新开始传输整个文件的技术。
这项技术在网络文件传输中被广泛应用,能够显著提高文件传输的效率和可靠性。
断点续传的原理主要涉及到文件传输的断点记录和续传处理两个方面。
首先,在文件传输过程中,系统会记录每个传输块的传输状态和位置信息,当传输中断时,系统可以根据这些记录信息确定断点位置。
其次,系统在传输中断后,可以通过断点位置和传输记录信息,从断点处继续传输文件,而不需要重新传输已经传输过的部分。
断点续传的实现依赖于以下几个关键技术:1. 断点记录技术,在文件传输过程中,系统需要记录每个传输块的传输状态和位置信息。
这些记录信息通常包括传输块的起始位置、传输状态(已传输、未传输)、传输进度等。
通过这些记录信息,系统可以准确确定传输中断时的断点位置。
2. 断点续传处理技术,当传输中断后,系统需要根据断点位置和传输记录信息,从断点处继续传输文件。
这就需要系统能够准确地识别断点位置,并能够根据传输记录信息,恢复传输过程。
通常,系统会通过读取断点位置附近的传输记录信息,重新建立传输连接,并从断点处继续传输文件。
3. 数据校验技术,在断点续传过程中,为了确保续传的数据完整性,系统通常会采用数据校验技术。
这些技术可以在传输过程中对数据进行校验,确保传输的数据完整性和正确性。
当传输中断后,系统可以通过校验数据来验证断点处的数据完整性,从而确保续传的数据准确无误。
断点续传技术的应用可以显著提高文件传输的效率和可靠性。
通过断点续传,用户可以在传输中断后,无需重新传输整个文件,节省了传输时间和带宽资源。
同时,断点续传也提高了文件传输的可靠性,即使在网络不稳定或传输中断的情况下,用户也可以通过断点续传技术来确保文件传输的完整性和正确性。
总之,断点续传技术通过断点记录和续传处理等关键技术的应用,实现了在文件传输中断后,可以从断点处继续传输文件的功能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
和前面服务器返回的信息比较一下,就会发现增加了一行: Content-Range=bytes 2000070-106786027/106786028 返回的代码也改为 206 了,而不再是 200 了。
知道了以上原理,就可以进行断点续传的编程了。
Java 实现断点续传的关键几点
1. (1) 用什么方法实现提交 RANGE: bytes=2000070-。 当然用最原始的 Socket 是肯定能完成的,不过那样太费事了,其实 Java 的 net 包中提供了这种功能。代码如下:
从输入流中取出的字节流就是 down.zip 文件从 2000070 开始的字节流。 大家看,其实断点续传用 Java 实现起来还是很简单的吧。接下来要做的 事就是怎么保存获得的流到文件中去了。
2. 保存文件采用的方法。 我采用的是 IO 包中的 RandAccessFile 类。 操作相当简单,假设从 2000070 处开始保存文件,代码如下: RandomAccess oSavedFile = new RandomAccessFile("down.zip","rw"); long nPos = 2000070; // 定位文件指针到 nPos 位置 oSavedFile.seek(nPos); byte[] b = new byte[1024];
URL url = new URL("/down.zip"); HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection();
// 设置 User-Agent httpConnection.setRequestProperty("User-Agent","NetFox"); // 设置断点续传的开始位置 httpConnection.setRequestProperty("RANGE","bytes=2000070"); // 获得输入流 InputStream input = httpConnection.getInputStream();
下面是源程序:
/* /* * SiteFileFetch.java */ package NetFox; import java.io.*; import .*; public class SiteFileFetch extends Thread { SiteInfoBean siteInfoBean = null; // 文件信息 Bean long[] nStartPos; // 开始位置 long[] nEndPos; // 结束位置 FileSplitterFetch[] fileSplitterFetch; // 子线程对象 long nFileLength; // 文件长度 boolean bFirst = true; // 是否第一次取文件 boolean bStop = false; // 停止标志 File tmpFile; // 文件下载的临时信息 DataOutputStream output; // 输出到文件的输出流
{ nEndPos[i] = nStartPos[i+1]; } nEndPos[nEndPos.length-1] = nFileLength; } } // 启动子线程 fileSplitterFetch = new FileSplitterFetch[nStartPos.length]; for(int i=0;i<nStartPos.length;i++) { fileSplitterFetch[i] = new FileSplitterFetch(siteInfoBean.getSSiteURL(), siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(), nStartPos[i],nEndPos[i],i); Utility.log("Thread " + i + " , nStartPos = " + nStartPos[i] + ", nEndPos =" + nEndPos[i]); fileSplitterFetch[i].start(); } // fileSplitterFetch[nPos.length-1] = new FileSplitterFetch(siteInfoBean.getSSiteURL(), siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(),nPos[nPos.length-1],nFileLength,nPos.leng th-1); // Utility.log("Thread " +(nPos.length-1) + ",nStartPos = "+nPos[nPos.length-1]+", nEndPos = " + nFileLength); // fileSplitterFetch[nPos.length-1].start(); // 等待子线程结束 //int count = 0; // 是否结束 while 循环 boolean breakWhile = false; while(!bStop) { write_nPos(); Utility.sleep(500); breakWhile = true; for(int i=0;i<nStartPos.length;i++) { if(!fileSplitterFetch[i].bDownOver) { breakWhile = false;
public SiteFileFetch(SiteInfoBean bean) throws IOException { siteInfoBean = bean; //tmpFile = File.createTempFile ("zhong","1111",new File(bean.getSFilePath())); tmpFile = new File(bean.getSFilePath()+File.separator + bean.getSFileName()+".info"); if(tmpFile.exists ()) { bFirst = false; read_nPos(); } else { nStartPos = new long[bean.getNSplitter()]; nEndPos = new long[bean.getNSplitter()]; } } public void run() { // 获得文件长度 // 分割文件 // 实例 FileSplitterFetch // 启动 FileSplitterFetch 线程 // 等待子线程返回 try{ if(bFirst) { nFileLength = getFileSize(); if(nFileLength == -1) { System.err.println("File Length is not known!"); } else if(nFileLength == -2) { System.err.println("File is not access!"); } else { for(int i=0;i<nStartPos.length;i++) { nStartPos[i] = (long)(i*(nFileLength/nStartPos.length)); } for(int i=0;i<nEndPos.length-1;i++)
用 Java 实现断点续传 (HTTP)
断点续传的原理
其实断点续传的原理很简单,就是在 Http 的请求上和一般的下载有所不同而已。 打个比方,浏览器请求服务器上的一个文时,所发出的请求如下: 假设服务器域名为 ,文件名为 down.zip。 GET /down.zip HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.msexcel, application/msword, application/vnd.ms-powerpoint, */* Accept-Language: zh-cn Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0) Connection: Keep-Alive
仔细看一下就会发现多了一行 RANGE: bytes=2000070这一行的意思就是告诉服务器 down.zip 这个文件从 2000070 字节开始传,前 面的字节不用传了。 服务器收到这个请求以后,返回的信息如下: 206 Content-tent-Range=bytes 2000070-106786027/106786028 Date=Mon, 30 Apr 2001 12:55:20 GMT ETag=W/"02ca57e173c11:95b" Content-Type=application/octet-stream Server=Microsoft-IIS/5.0 Last-Modified=Mon, 30 Apr 2001 12:55:20 GMT