HttpURLConnection實現檔案斷點續傳
阿新 • • 發佈:2019-01-27
首先
client端:
[java] view plain copy print?- 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 = newbyte[bufferSizeUpload];
- int len = -1;
- long currentUploadSize = offset;
- fin.skip(offset);
- while ((len = fin.read(buf)) != -1¤tUploadSize<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();
- thrownew RuntimeException("Release resource failed.");
- }
- }
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¤tUploadSize<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?- 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);
- returnnull;
- }
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?- RandomAccessFile raFile = new RandomAccessFile(uploadFile.getAbsolutePath(), "rw");
- raFile.seek(uploadFile.length());
RandomAccessFile raFile = new RandomAccessFile(uploadFile.getAbsolutePath(), "rw");
raFile.seek(uploadFile.length());
方法進行根據傳輸大小實時進行檔案讀寫。
[java] view plain copy print?- publicstaticvoid 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();
- }
- }
- publicstaticlong uploadFile(String offset,String destFileName,BufferedInputStream bis)
- throws IOException{
- File uploadFile = new File(destFileName);
- int len = 0;
- byte[] bt = newbyte[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 ;
- }
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 ;
}
首先建立一個空檔案,接下來根據每次接收的檔案流及檔案長度 寫入檔案。