1. 程式人生 > >HttpURLConnection實現檔案斷點續傳

HttpURLConnection實現檔案斷點續傳

首先

client端:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. HttpURLConnection conn = null;  
  2.         BufferedInputStream fin = null;  
  3.         BufferedOutputStream out = null;  
  4.         URL reqUrl;  
  5.         try {  
  6.             reqUrl = new URL("http://<ip>:<port>/Emergency/phone/attachmentUpload");  
  7.             conn = (HttpURLConnection) reqUrl.openConnection();  
  8.             conn.setConnectTimeout(3000);  
  9.             conn.setRequestMethod("PUT");  
  10.             if(isCommit){  
  11.                 conn.setRequestProperty("isCommit""true");  
  12.             }else{  
  13.                 conn.setRequestProperty("isCommit""false");  
  14.             }  
  15.             conn.setRequestMethod("PUT"
    );  
  16.             conn.setRequestProperty("Content-Type""binary/octet-stream");  
  17.             conn.setRequestProperty("offset", StringUtil.toString(offset));  
  18.             conn.setDoOutput(true);  
  19.             conn.setDoInput(true);  
  20.             // 1M的chunk緩衝
  21.             conn.setChunkedStreamingMode(1024*1024
    );  
  22.             out = new BufferedOutputStream(conn.getOutputStream());  
  23.             fin = new BufferedInputStream(new FileInputStream(file));  
  24.             byte[] buf = newbyte[bufferSizeUpload];  
  25.             int len = -1;  
  26.             long currentUploadSize = offset;  
  27.             fin.skip(offset);  
  28.             while ((len = fin.read(buf)) != -1&currentUploadSize<offset+uploadSize) {  
  29.                 if(offset+uploadSize-currentUploadSize<bufferSizeUpload){  
  30.                     len = Integer.parseInt(StringUtil.toString(offset+uploadSize-currentUploadSize));  
  31.                 }  
  32.                 if(len>0){  
  33.                     if(out!=null){  
  34.                         out.write(buf, 0, len);  
  35.                         out.flush();  
  36.                     }  
  37.                 }  
  38.                 currentUploadSize += len;  
  39.             }  
  40.         } catch (SocketTimeoutException e) {  
  41.             e.printStackTrace();  
  42.         } catch(IOException e){  
  43.             e.printStackTrace();  
  44.         } finally {  
  45.             try {  
  46.                 if (fin != null) {  
  47.                     fin.close();  
  48.                     fin = null;  
  49.                 }  
  50.                 if (out != null) {  
  51.                     out.close();  
  52.                     out = null;  
  53.                 }  
  54.                 if (conn != null) {  
  55.                     conn.disconnect();  
  56.                     conn = null;  
  57.                 }  
  58.             } catch (IOException ioe) {  
  59.                 ioe.printStackTrace();  
  60.                 thrownew RuntimeException("Release resource failed.");  
  61.             }  
  62.         }  
HttpURLConnection conn = null;
		BufferedInputStream fin = null;
		BufferedOutputStream out = null;
		URL reqUrl;
		try {
			reqUrl = new URL("http://<ip>:<port>/Emergency/phone/attachmentUpload");
			conn = (HttpURLConnection) reqUrl.openConnection();
			conn.setConnectTimeout(3000);
			conn.setRequestMethod("PUT");
			if(isCommit){
				conn.setRequestProperty("isCommit", "true");
			}else{
				conn.setRequestProperty("isCommit", "false");
			}
			conn.setRequestMethod("PUT");
			conn.setRequestProperty("Content-Type", "binary/octet-stream");
			conn.setRequestProperty("offset", StringUtil.toString(offset));
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 1M的chunk緩衝
			conn.setChunkedStreamingMode(1024*1024);
			out = new BufferedOutputStream(conn.getOutputStream());
			fin = new BufferedInputStream(new FileInputStream(file));
			byte[] buf = new byte[bufferSizeUpload];
			int len = -1;
			long currentUploadSize = offset;
			fin.skip(offset);
			while ((len = fin.read(buf)) != -1&currentUploadSize<offset+uploadSize) {
				if(offset+uploadSize-currentUploadSize<bufferSizeUpload){
					len = Integer.parseInt(StringUtil.toString(offset+uploadSize-currentUploadSize));
				}
				if(len>0){
					if(out!=null){
						out.write(buf, 0, len);
						out.flush();
					}
				}
				currentUploadSize += len;
			}
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
		} catch(IOException e){
			e.printStackTrace();
		} finally {
			try {
				if (fin != null) {
					fin.close();
					fin = null;
				}
				if (out != null) {
					out.close();
					out = null;
				}
				if (conn != null) {
					conn.disconnect();
					conn = null;
				}
			} catch (IOException ioe) {
				ioe.printStackTrace();
				throw new RuntimeException("Release resource failed.");
			}
		}

如上所示:url引數通過setRequestProperty方法放在請求頭中 ,而檔案流放在 body 中。

同時需要注意 HttpURLConnection.setChunkedStreamingMode 此方法保證每次檔案流達到指定大小就傳送一次,避免了放在快取並一次性傳輸中可能遇到的資料缺失。

服務端:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. public String underUpload() throws IOException{  
  2.         String data = request.getHeader("data");   
  3.         String userInfo = request.getHeader("userInfo");   
  4.         userInfo = new String(userInfo.getBytes("iso-8859-1"),"GBK");  
  5.         //System.out.println(data);
  6.         //System.out.println(userInfo);
  7.         Map<String,String> data_map = gson.fromJson(data,attachVo.data_map.getClass());  
  8.         if(data_map!=null) attachVo.data_map=data_map;  
  9.         attachVo.user = gson.fromJson(userInfo,attachVo.user.getClass());  
  10.         apiService.attachUpload(attachVo,new BufferedInputStream(request.getInputStream()));  
  11.         //response.setStatus(200);
  12.         returnnull;  
  13.     }  
public String underUpload() throws IOException{
		String data = request.getHeader("data"); 
		String userInfo = request.getHeader("userInfo"); 
		userInfo = new String(userInfo.getBytes("iso-8859-1"),"GBK");
		//System.out.println(data);
		//System.out.println(userInfo);
		Map<String,String> data_map = gson.fromJson(data,attachVo.data_map.getClass());
		if(data_map!=null) attachVo.data_map=data_map;
		attachVo.user = gson.fromJson(userInfo,attachVo.user.getClass());
		apiService.attachUpload(attachVo,new BufferedInputStream(request.getInputStream()));
		//response.setStatus(200);
		return null;
	}

使用的是ssh架構 ,通過getHeader 得到 url引數,通過getInputStream得到檔案流,同時還要控制好編碼,以防中文亂碼。

至於斷點續傳,基本思想是通過資訊頭的部分 傳遞每次傳輸的檔案大小,與伺服器端的檔案大小匹配。並通過

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. RandomAccessFile raFile = new RandomAccessFile(uploadFile.getAbsolutePath(), "rw");  
  2.         raFile.seek(uploadFile.length());  
RandomAccessFile raFile = new RandomAccessFile(uploadFile.getAbsolutePath(), "rw");
		raFile.seek(uploadFile.length());

方法進行根據傳輸大小實時進行檔案讀寫。

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicstaticvoid saveFile(String destFilePathStr,String destFileName){  
  2.         try {  
  3.             File destFilePath = new File(destFilePathStr);  
  4.             if(!destFilePath.exists()){  
  5.                 destFilePath.mkdirs();  
  6.                 destFilePath = null;  
  7.             }  
  8.             File destFile = new File(destFilePathStr+"//"+destFileName);  
  9.             if(!destFile.exists()){  
  10.                 destFile.createNewFile();  
  11.             }  
  12.         } catch (Exception e) {  
  13.             e.printStackTrace();  
  14.         }  
  15.     }  
  16.     publicstaticlong uploadFile(String offset,String destFileName,BufferedInputStream bis)   
  17.     throws IOException{  
  18.         File uploadFile = new File(destFileName);  
  19.         int len = 0;  
  20.         byte[] bt = newbyte[1024];  
  21.         RandomAccessFile raFile = new RandomAccessFile(uploadFile.getAbsolutePath(), "rw");  
  22.         raFile.seek(uploadFile.length());  
  23.         while ((len = bis.read(bt)) > 0){  
  24.             raFile.write(bt, 0, len);  
  25.         }  
  26.         long l = raFile.length();  
  27.         try {  
  28.              if(bis != null)  
  29.                  bis.close();  
  30.              if (raFile != null)  
  31.                  raFile.close();  
  32.         } catch (IOException e) {  
  33.             l = 0;  
  34.             e.printStackTrace();  
  35.         }  
  36.         return l ;  
  37.     }  
public static void saveFile(String destFilePathStr,String destFileName){
		try {
			File destFilePath = new File(destFilePathStr);
			if(!destFilePath.exists()){
				destFilePath.mkdirs();
				destFilePath = null;
			}
			File destFile = new File(destFilePathStr+"//"+destFileName);
			if(!destFile.exists()){
				destFile.createNewFile();
			}
	
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static long uploadFile(String offset,String destFileName,BufferedInputStream bis) 
	throws IOException{
		File uploadFile = new File(destFileName);
		int len = 0;
		byte[] bt = new byte[1024];
		RandomAccessFile raFile = new RandomAccessFile(uploadFile.getAbsolutePath(), "rw");
		raFile.seek(uploadFile.length());
	    while ((len = bis.read(bt)) > 0){
	    	raFile.write(bt, 0, len);
    	}
	    long l = raFile.length();
	    try {
		     if(bis != null)
		    	 bis.close();
		     if (raFile != null)
		    	 raFile.close();
		     
		} catch (IOException e) {
			l = 0;
		    e.printStackTrace();
		}
		return l ;
	}

首先建立一個空檔案,接下來根據每次接收的檔案流及檔案長度 寫入檔案。