麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

用Java實現(xiàn)斷點續(xù)傳(HTTP)

2019-11-18 13:26:16
字體:
供稿:網(wǎng)友

  作者: 鐘華([email protected])
  內(nèi)容:
  (一)斷點續(xù)傳的原理
  (二)java實現(xiàn)斷點續(xù)傳的要害幾點
  (三)斷點續(xù)傳內(nèi)核的實現(xiàn)
  (一)斷點續(xù)傳的原理
  其實斷點續(xù)傳的原理很簡單,就是在Http的請求上和一般的下載有所不同而已。
  打個比方,瀏覽器請求服務(wù)器上的一個文時,所發(fā)出的請求如下:
  假設(shè)服務(wù)器域名為wwww.sjtu.edu.cn,文件名為down.zip
  GET /down.zip HTTP/1.1
  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
  Excel, 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
  服務(wù)器收到請求后,按要求尋找請求的文件,提取文件的信息,然后返回給瀏覽器,返回信息如下:
  200
  Content-Length=106786028
  Accept-Ranges=bytes
  Date=Mon, 30 APR 2001 12:56:11 GMT
  ETag=W/"02ca57e173c11:95b"
  Content-Type=application/octet-stream
  Server=Microsoft-IIS/5.0
  Last-Modified=Mon, 30 Apr 2001 12:56:11 GMT
  所謂斷點續(xù)傳,也就是要從文件已經(jīng)下載的地方開始繼續(xù)下載。所以在客戶端瀏覽器傳給
  Web服務(wù)器的時候要多加一條信息--從哪里開始。
  下面是用自己編的一個"瀏覽器"來傳遞請求信息給Web服務(wù)器,要求從2000070字節(jié)開始。
  GET /down.zip HTTP/1.0
  User-Agent: NetFox
  RANGE: bytes=2000070-
  Accept: text/Html, image/gif, image/jpeg, *; q=.2, */*; q=.2
  仔細(xì)看一下就會發(fā)現(xiàn)多了一行RANGE: bytes=2000070-
  這一行的意思就是告訴服務(wù)器down.zip這個文件從2000070字節(jié)開始傳,前面的字節(jié)不用傳了。
  服務(wù)器收到這個請求以后,返回的信息如下:
  206
  Content-Length=106786028
  Content-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
  和前面服務(wù)器返回的信息比較一下,就會發(fā)現(xiàn)增加了一行:
  Content-Range=bytes 2000070-106786027/106786028
  返回的代碼也改為206了,而不再是200了。
  知道了以上原理,就可以進(jìn)行斷點續(xù)傳的編程了。
  (二)Java實現(xiàn)斷點續(xù)傳的要害幾點
  (1)用什么方法實現(xiàn)提交RANGE: bytes=2000070-。
  當(dāng)然用最原始的Socket是肯定能完成的,不過那樣太費事了,其實Java的net包中提供了這種功能。代碼如下:
  URL url = new URL("http://www.sjtu.edu.cn/down.zip");
  HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection
  ();
  //設(shè)置User-Agent
  httpConnection.setRequestProperty("User-Agent","NetFox");
  //設(shè)置斷點續(xù)傳的開始位置
  httpConnection.setRequestProperty("RANGE","bytes=2000070");
  //獲得輸入流
  InputStream input = httpConnection.getInputStream();
  從輸入流中取出的字節(jié)流就是down.zip文件從2000070開始的字節(jié)流。
  大家看,其實斷點續(xù)傳用Java實現(xiàn)起來還是很簡單的吧。
  接下來要做的事就是怎么保存獲得的流到文件中去了。
  保存文件采用的方法。
  我采用的是IO包中的RandaccessFile類。
  操作相當(dāng)簡單,假設(shè)從2000070處開始保存文件,代碼如下:
  RandomAccess oSavedFile = new RandomAccessFile("down.zip","rw");
  long nPos = 2000070;
  //定位文件指針到nPos位置
  oSavedFile.seek(nPos);
  byte[] b = new byte[1024];
  int nRead;
  //從輸入流中讀入字節(jié)流,然后寫到文件中
  while((nRead=input.read(b,0,1024)) > 0)
  {
  oSavedFile.write(b,0,nRead);
  }
  怎么樣,也很簡單吧。
  接下來要做的就是整合成一個完整的程序了。包括一系列的線程控制等等。
  (三)斷點續(xù)傳內(nèi)核的實現(xiàn)
  主要用了6個類,包括一個測試類。
  SiteFileFetch.java負(fù)責(zé)整個文件的抓取,控制內(nèi)部線程(FileSplitterFetch類)。
  FileSplitterFetch.java負(fù)責(zé)部分文件的抓取。
  FileAccess.java負(fù)責(zé)文件的存儲。
  SiteInfoBean.java要抓取的文件的信息,如文件保存的目錄,名字,抓取文件的URL等。
  Utility.java工具類,放一些簡單的方法。
  TestMethod.java測試類。
  下面是源程序:
  /*
  **SiteFileFetch.java
  */
  package NetFox;
  import java.io.*;
  import java.net.*;
  public class SiteFileFetch extends Thread {
  SiteInfoBean siteInfoBean = null; //文件信息Bean
  long[] nStartPos; //開始位置
  long[] nEndPos; //結(jié)束位置
  FileSplitterFetch[] fileSplitterFetch; //子線程對象
  long nFileLength; //文件長度
  boolean bFirst = true; //是否第一次取文件
  boolean bStop = false; //停止標(biāo)志
  File tmpFile; //文件下載的臨時信息
  DataOutputStream output; //輸出到文件的輸出流
  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[i] = (long)(i*(nFileLength/nStartPos.length));
  }
  for(int i=0;i  {
  nEndPos[i] = nStartPos[i+1];
  }
  nEndPos[nEndPos.length-1] = nFileLength;
  }
  }
  //啟動子線程
  fileSplitterFetch = new FileSplitterFetch[nStartPos.length];
  for(int i=0;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.length-1);
  // Utility.log("Thread " + (nPos.length-1) + " , nStartPos = " + nPos[nPos.length-1] + ",
  nEndPos = " + nFileLength);
  // fileSplitterFetch[nPos.length-1].start();
  //等待子線程結(jié)束
  //int count = 0;
  //是否結(jié)束while循環(huán)
  boolean breakWhile = false;
  while(!bStop)
  {
  write_nPos();
  Utility.sleep(500);
  breakWhile = true;
  for(int i=0;i  {
  if(!fileSplitterFetch[i].bDownOver)
  {
  breakWhile = false;
  break;
  }
  }
  if(breakWhile)
  break;
  //count++;
  //if(count>4)
  // siteStop();
  }
  System.err.println("文件下載結(jié)束!");
  }
  catch(Exception e){e.printStackTrace ();}
  }
  //獲得文件長度
  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 ());
  //Utili

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 欧美精品激情视频 | 羞羞的视频免费在线观看 | 国产精品久久久久一区二区 | 免费网站看毛片 | 日韩毛片网 | 在线免费av网站 | 亚洲欧美不卡视频 | a视频网站 | 得得啪在线视频 | 久久精品视频7 | 国产一区网址 | 精品国产欧美一区二区 | 五月婷婷第四色 | 免费一级欧美大片视频 | 4399一级成人毛片 | 一本大道av | 性少妇videosexfreexx入片 | 日韩中文字幕一区二区三区 | 国产成人精品免高潮在线观看 | 黄网站免费入口 | 羞羞答答视频 | 久久老司机 | 国产精品久久久久久久av | 国产免费一级大片 | 一本在线高清码电影 | 本色视频aaaaaa一级网站 | 51国产偷自视频区视频小蝌蚪 | 国产精品久久av | 9797色 | 成人做爰高潮片免费视频韩国 | 国产一区二区三区四区波多野结衣 | 人成久久 | 一级做受大片免费视频 | 青草视频在线观看视频 | 成人短视频在线播放 | 最新精品在线 | 国产精品久久77777 | 国产一国产精品一级毛片 | 澳门一级淫片免费视频 | 国产成人精品自拍视频 | 99ri在线|