SoFunction
Updated on 2025-03-08

Implementation based on the principle of continuous transmission of breakpoints

Requirement background

When downloading dynamically created files, I hope the browser will display the download progress.

The files created dynamically are expected to be downloaded in segments

HTTP breakpoint continues to transmit messages

To achieve HTTP breakpoint continuous transmission, you must briefly understand the following packets.

Accept-Ranges tells the client (browser...) that the server side supports breakpoint continuous transmission and the server side returns

Range client tells the server to download resources from the specified location/range (the number of bytes here) and the client sends it

Content-Range The server side tells the client the data information of the response, and the byte position of this part in the entire return body. The server side returns

ETag resource identification Non-necessary server-side return

Last-Modified The time of the last update of the resource Non-essential Return on the server side

Range's range format

Indicates 0-499 byte range: Range: bytes=0-499

Represents the last 500 byte range: Range: bytes=-500

Indicates 500 bytes start to end range: Range: bytes=500-

Represents the first and last bytes: Range: bytes=0-0,-1

Indicates that several ranges are specified at the same time: Range: bytes=500-600,601-999

Content-Range data format

Content-Range: bytes 0-499/22036: means return 0-499 byte range data. The resource has a total of 22036 bytes.

principle

Client initiates a request Set Range to specify the number of start bytes or end bytes If it starts from 0, you can also not set it.

The server checks the client Range header to parse the number of start bytes and end bytes and returns the message header. Accept-Ranges indicates that it supports breakpoint continuous transmission. Content-Range records the location information of the stream written to the client this time, and then writes the stream to the client.

The server can use ETag Last-Modified to mark whether the resource has been modified. Do some verification work. If the verification fails, an error will be returned, and non-essential items will be returned.

Java implementation

OutputStream os=null;
 InputStream inputStream =null;
 File zipFile=null;
 try{
  long zipStart=();
  zipFile=createFile();//Dynamicly create files based on business  if(()){
   (("compressionZIP Spend time %s(s) ",
  (()-zipStart)/1000));
  }
  if (()) {
   long downloadStart=();
   inputStream= new BufferedInputStream(new FileInputStream(zipFile));
   ();
   os=new BufferedOutputStream(());
   String userAgent = ("USER-AGENT");
   String fileName=();
   if (null != userAgent && -1 != ("MSIE")) {
    fileName = (fileName, "UTF8");
   } else if (null != userAgent && -1 != ("Mozilla")) {
    fileName = new String(("utf-8"), "ISO-8859-1");
   }
   ("Accept-Ranges", "bytes");
   ("Content-Disposition", 
  "attachment;filename="+ fileName);
   (MediaType.APPLICATION_OCTET_STREAM_VALUE);
   long pos = 0, fileSize=(),
 last=fileSize-1;
   ("ETag",().
   concat((fileSize))
     .concat("_").concat((())));
   ("Last-Modified",());
   ("Expires",
   ()+1000*60*60*24);
   if (null != ("Range")) {
    (HttpServletResponse.SC_PARTIAL_CONTENT);
    try {
     // Only these two range formats are processed for the time being. 1. RANGE: bytes=111- 2. Range: bytes=0-499     String numRang = ("Range")
   .replaceAll("bytes=", "");
     String[] strRange = ("-");
     if ( == 2) {
      pos = (strRange[0].trim());
      last = (strRange[1].trim());
     } else {
      pos = (("-", "").trim());
     }
    } catch (NumberFormatException e) {
     (("Range") + " error");
     pos = 0;
    }
   }
   long rangLength = last - pos + 1;
   String contentRange = new StringBuffer("bytes ").
   append((pos)).
   append("-").append(last).append("/").
   append((fileSize)).toString();
   ("Content-Range", contentRange);
   ("Content-Length",(rangLength));
   if(pos>0){
    (pos);
   }
   byte[] buffer = new byte[1024*512];//Download at 512KB 0.5MB of traffic each time   int length = 0,sendTotal=0;
   while (sendTotal < rangLength && length!=-1) {
    length = (buffer, 0,
  ((rangLength - sendTotal) <=  ?
      ((int) (rangLength - sendTotal)) : ));
    sendTotal = sendTotal + length;
    (buffer, 0, length);
   }
   if(os!=null){
    ();
   }
   if(()){
    (("download Spend time %s(s) ",
  (()-downloadStart)/1000));
   }
  }
 }catch (Exception e){
  if(((),"Broken pipe")){
   ("User Cancel Download");
  }
  ((),e);
 }finally {
  if(os!=null){
   try{
    ();
   }catch (Exception e){}
  }
  if(inputStream!=null){
   try{
    (inputStream);
   }catch (Exception e){}
  }
 }
}

For example, when downloading Google browser, you can see the download progress and pause the download and resume the download operation. You can also set up Range test segment downloads.

The above article is based on the principle of breakpoint continuous transmission download. This is all the content I share with you. I hope you can give you a reference and I hope you can support me more.