將多個檔案進行壓縮處理,然後傳輸到伺服器
阿新 • • 發佈:2019-01-08
目前專案正需要多個檔案壓縮上傳,在這裡遇到一些坑與解決方案。
我這裡的問題是從印表機影印,掃描時候的留底檔案。在拿到檔案路徑後,就要根據這個路徑拿到檔案,進行壓縮傳輸,可供下載。
其中遇到的問題
1、使用這個thumbnailator-0.4.7.jar對圖片進行再壓縮,會十分損耗資源,以至於在印表機列印完成後,直接卡住。這個壓縮工具慎用!
2、在不使用上面這個工具傳輸的時候,即時原大小的檔案,上傳速度也是可行的。只是在一次性將流檔案直接傳輸給壓縮流,會出現檔案流疊加的問題
從而導致檔案顯示出現問題。解決辦法是流在傳輸的時候,分段傳輸,這樣就不會出現這種問題。
@3.http://blog.csdn.net/zx4321/article/details/7712290
通過下面的方式,就可以將多個圖片壓縮成一個壓縮流。這樣就可以靈活操作這個檔案流了
遍歷目錄檔案,獲取最終的檔案/** * 獲取多個壓縮檔案的流檔案 * @param bytesList * @param nameList * @param fileList * @param compress * @return * @throws Exception */ public static byte[] zipBytes(ArrayList<String> nameList,ArrayList<File> fileList) throws Exception { ByteArrayOutputStream tempByteOStream = null; BufferedOutputStream tempBufferOStream = null; ZipOutputStream tempZStream = null; ZipEntry tempEntry = null; byte[] tempBytes = null; tempByteOStream = new ByteArrayOutputStream(); CheckedOutputStream csum1 = new CheckedOutputStream(tempByteOStream, new Adler32()); tempZStream = new ZipOutputStream(csum1); tempBufferOStream = new BufferedOutputStream(tempZStream); for(int i=0;i<fileList.size();i++){ FileInputStream in=new FileInputStream(fileList.get(i)); byte [] buff=new byte[1024]; // 輸出校驗流,採用Adler32更快 tempZStream.setEncoding("UTF-8"); tempEntry = new ZipEntry(nameList.get(i)); tempZStream.putNextEntry(tempEntry); /*if (compress) { bytes= CompressPictureTools.compressOfQuality(fileList.get(i), 0); }*/ /*else{ bytes= CompressPictureTools.compressOfQuality(fileList.get(i), 1); }*/ int len=0; while((len=in.read(buff))!=-1){ tempZStream.write(buff, 0, len); } } tempBufferOStream.flush(); tempByteOStream.flush(); tempZStream.closeEntry(); tempZStream.close(); tempBytes = tempByteOStream.toByteArray(); tempByteOStream.close(); tempBufferOStream.close(); return tempBytes; }
/** * 遍歷檔案目錄 * @param path */ public static void getFiles( URI path ) { ArrayList<String> filelist = new ArrayList<String>(); File root = new File( path ); File[] files = root.listFiles(); System.out.println("======================[AuditSample] File Exists :================"+root); System.out.println("======================[AuditSample] File listFiles :================"+files); for ( File file : files ) { if ( file.isDirectory() ) { try { getFiles(new URI(file.getAbsolutePath())); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } filelist.add( file.getAbsolutePath() ); System.out.println( "顯示" + path + "下所有子目錄及其檔案" + file.getAbsolutePath() ); }else{ System.out.println( "顯示" + path + "下所有子目錄" + file.getAbsolutePath() ); } } }
這裡,我採用了多執行緒處理的方式來處理上傳檔案,這樣就不會影響主執行緒進行其他操作了
package com.bips.samsung.utils;
import java.io.File;
import java.io.FileInputStream;
import java.net.URI;
import java.util.ArrayList;
import com.bips.samsung.service.HttpService;
import com.bips.samsung.service.impl.HttpServiceImpl;
public class UploadFiles implements Runnable{
private URI uri;
private String sessionId;
private String jobId;
private String fileType;
private String tokenID;
public UploadFiles(URI uri,String sessionId,String jobId,String fileType,String tokenID){
this.uri=uri;
this.sessionId=sessionId;
this.jobId=jobId;
this.fileType=fileType;
this.tokenID=tokenID;
}
/**
* 上傳圖片壓縮包到伺服器
* @param uri
* @return
*/
@Override
public void run() {
System.out.println("=========================檔案開始上傳!============================"+System.currentTimeMillis());
HttpService httpService=new HttpServiceImpl();
try {
//遍歷檔案目錄下的檔案
FTPUtils.getFiles(uri);
File file=new File(uri);
ArrayList<File> fileList=new ArrayList<File>();
ArrayList<String> list=new ArrayList<String>();
ArrayList<FileInputStream> inputStreamList=new ArrayList<FileInputStream>();
FileInputStream filein=null;
if(file.exists()){
File[] listFiles = file.listFiles();
for(int i=0;i<listFiles.length;i++){
String absolutePath=listFiles[i].getAbsolutePath();
System.out.println("絕對路徑為:"+listFiles[i].getAbsolutePath());
if(absolutePath.endsWith(".jpg")){
File absfil=new File(new URI("file:"+absolutePath));
filein=new FileInputStream(absfil);
fileList.add(listFiles[i]);
inputStreamList.add(filein);
list.add(absolutePath.substring(absolutePath.lastIndexOf("/")+1));
}
}
byte[] zipBytes = CommonUtil.zipBytes(list,fileList);
//ByteArrayInputStream byteArray=new ByteArrayInputStream();
httpService.UploadFile(zipBytes,sessionId,jobId,fileType,tokenID);
System.out.println("===========================上傳檔案成功======================"+System.currentTimeMillis());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
自己定義http傳輸協議,進行檔案上傳
/**
* 上傳壓縮檔案
* @param url
* @param params
* @param zipBytes
* @return
* @throws Exception
*/
public static URLConnection uploadFile(String url, Map<String, String> params, byte [] zipBytes){
final String BOUNDARY = "---------------------------7da2137580612"; //資料分隔線
final String endline ="--"+BOUNDARY + "--\r\n";//資料結束標誌
HttpURLConnection conn=null;
StringBuffer strBuf1=null;
StringBuffer strBuf2=null;
System.out.println("json字串資訊為\r\n"+JSON.toJSONString(params));
if (params != null && !params.isEmpty()) {
strBuf1= new StringBuffer();
strBuf1.append("--");
strBuf1.append(BOUNDARY);
strBuf1.append("\r\n");
strBuf1.append("Content-Disposition: form-data; name=\"json"+"\"\r\n\r\n");
strBuf1.append(JSON.toJSONString(params));
strBuf1.append("\r\n");
strBuf1.append("--");
strBuf1.append(BOUNDARY);
strBuf1.append("\r\n");
}
if(zipBytes.length>0){
strBuf2= new StringBuffer();
strBuf2.append("Content-Disposition: form-data; name=\"file"+"\"; filename=\"copyOrScan.zip"+"\"\r\n");
strBuf2.append("Content-Type: image/jpeg/zip" + "\r\n\r\n");
}
int dataLength = strBuf1.toString().getBytes().length+strBuf2.length()+zipBytes.length;
try {
//封裝請求內容
URL url1 = new URL(url);
conn= (HttpURLConnection) url1.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
conn.setReadTimeout(30000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
//設定請求頭
conn.setRequestProperty("Accept", "Accept: text/html, application/xaml+xml,*/*");
conn.setRequestProperty("Content-type", "multipart/form-data; boundary="+ BOUNDARY);
conn.setRequestProperty("Content-Length", dataLength+"");
conn.connect();
DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
ds.write(strBuf1.toString().getBytes("UTF-8"));
ds.write(strBuf2.toString().getBytes("UTF-8"));
InputStream in=new ByteArrayInputStream(zipBytes);
int buffSize=1024;
int length=-1;
byte [] buff=new byte[buffSize];
while((length=in.read(buff))!=-1){
ds.write(buff,0,length);
}
System.out.println("================位元組流總大小為==============="+zipBytes.length);
ds.flush();
ds.write("\r\n".getBytes("UTF-8"));
ds.write(endline.getBytes("UTF-8"));
ds.write("\r\n".getBytes("UTF-8"));
conn.getResponseCode(); // 為了傳送成功
ds.close();
return conn;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
另外還有一種表單上傳檔案的方式
/**
* 直接通過HTTP協議提交資料到伺服器,實現如下面表單提交功能:
* <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">
<INPUT TYPE="text" NAME="name">
<INPUT TYPE="text" NAME="id">
<input type="file" name="imagefile"/>
<input type="file" name="zip"/>
</FORM>
* @param path 上傳路徑(注:避免使用localhost或127.0.0.1這樣的路徑測試,因為它會指向手機模擬器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080這樣的路徑測試)
* @param params 請求引數 key為引數名,value為引數值
* @param file 上傳檔案
*/
@SuppressWarnings("resource")
public static boolean uploadFiles(String path, Map<String, String> params, FormFile[] files) throws Exception{
final String BOUNDARY = "---------------------------7da2137580612"; //資料分隔線
final String endline = "--" + BOUNDARY + "--\r\n";//資料結束標誌
int fileDataLength = 0;
if(files!=null&&files.length!=0){
for(FormFile uploadFile : files){//得到檔案型別資料的總長度
StringBuilder fileExplain = new StringBuilder();
fileExplain.append("--");
fileExplain.append(BOUNDARY);
fileExplain.append("\r\n");
fileExplain.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
fileExplain.append("\r\n");
fileDataLength += fileExplain.length();
if(uploadFile.getInStream()!=null){
fileDataLength += uploadFile.getFile().length();
}else{
fileDataLength += uploadFile.getData().length;
}
}
}
StringBuilder textEntity = new StringBuilder();
if(params!=null&&!params.isEmpty()){
for (Map.Entry<String, String> entry : params.entrySet()) {//構造文字型別引數的實體資料
textEntity.append("--");
textEntity.append(BOUNDARY);
textEntity.append("\r\n");
textEntity.append("Content-Disposition: form-data; name=\""+ entry.getKey() + "\"\r\n\r\n");
textEntity.append(entry.getValue());
textEntity.append("\r\n");
}
}
//計算傳輸給伺服器的實體資料總長度
int dataLength = textEntity.toString().getBytes().length + fileDataLength + endline.getBytes().length;
URL url = new URL(path);
int port = url.getPort()==-1 ? 80 : url.getPort();
Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);
OutputStream outStream = socket.getOutputStream();
//下面完成HTTP請求頭的傳送
String requestmethod = "POST "+ url.getPath()+" HTTP/1.1\r\n";
outStream.write(requestmethod.getBytes());
String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n";
outStream.write(accept.getBytes());
String language = "Accept-Language: zh-CN\r\n";
outStream.write(language.getBytes());
String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "\r\n";
outStream.write(contenttype.getBytes());
String contentlength = "Content-Length: "+ dataLength + "\r\n";
outStream.write(contentlength.getBytes());
String alive = "Connection: Keep-Alive\r\n";
outStream.write(alive.getBytes());
String host = "Host: "+ url.getHost() +":"+ port +"\r\n";
outStream.write(host.getBytes());
//寫完HTTP請求頭後根據HTTP協議再寫一個回車換行
outStream.write("\r\n".getBytes());
//把所有文字型別的實體資料傳送出來
outStream.write(textEntity.toString().getBytes());
//把所有檔案型別的實體資料傳送出來
if(files!=null&&files.length!=0){
for(FormFile uploadFile : files){
StringBuilder fileEntity = new StringBuilder();
fileEntity.append("--");
fileEntity.append(BOUNDARY);
fileEntity.append("\r\n");
fileEntity.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
outStream.write(fileEntity.toString().getBytes());
if(uploadFile.getInStream()!=null){
byte[] buffer = new byte[1024];
int len = 0;
while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1){
outStream.write(buffer, 0, len);
}
uploadFile.getInStream().close();
}else{
outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);
}
outStream.write("\r\n".getBytes());
}
}
//下面傳送資料結束標誌,表示資料已經結束
outStream.write(endline.getBytes());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if(reader.readLine().indexOf("200")==-1){//讀取web伺服器返回的資料,判斷請求碼是否為200,如果不是200,代表請求失敗
return false;
}
outStream.flush();
outStream.close();
reader.close();
socket.close();
return true;
}