1. 程式人生 > >檔案下載,上傳,壓縮,解壓

檔案下載,上傳,壓縮,解壓

package com.qb.chedai.server.util;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;


import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;






/**
 * 檔案處理器,主要處理的功能有: 
 * 1.向檔案伺服器上傳檔案 
 * 2.從檔案伺服器下載檔案 
 * 3.壓縮檔案 
 * 4.解壓縮檔案
 * 5.刪除目錄下的所有檔案及資料夾
 * 
 * @author qianll
 *
 */
/**
 * 壓縮依賴的jar包
 *                 <!-- CKFinder begin -->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.ckfinder</groupId>
            <artifactId>apache-ant-zip</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>com.ckfinder</groupId>
            <artifactId>ckfinder</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>com.ckfinder</groupId>
            <artifactId>ckfinderplugin-fileeditor</artifactId>
            <version>2.3</version>
        </dependency>
        <dependency>
            <groupId>com.ckfinder</groupId>
            <artifactId>ckfinderplugin-imageresize</artifactId>
            <version>2.3</version>
        </dependency>
        <!-- CKFinder end -->
 *
 */
public class FileProcessor {


/**
* The default buffer size to use.
*/
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

//private static String servicePicUploadURL = Global.getConfig("chedai.server.url") + "/basicservice/v1/weed";
private static String servicePicUploadURL = "http://192.168.1.182:10982"+"/basicservice/v1/weed";


/**
* 遞迴刪除資料夾(或檔案)

* @param path
*/
public static void deleteAllFilesOfDir(File path) {
if (!path.exists())
return;
if (path.isFile()) {
path.delete();
return;
}
File[] files = path.listFiles();
for (int i = 0; i < files.length; i++) {
deleteAllFilesOfDir(files[i]);
}
path.delete();
}


/**
* 從檔案伺服器下載檔案

* @param url
* @param file
*/
public static void downloadFromUrl(String url, File file) {
InputStream input = null;
FileOutputStream output = null;
try {
URL httpurl = new URL(url);
input = httpurl.openStream();
output = openOutputStream(file, false);
copy(input, output);
} catch (Exception e) {
throw new RuntimeException("圖片下載失敗,url:"+url, e);
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException ioe) {
// ignore
}
try {
if (output != null) {
output.close();
}
} catch (IOException ioe) {
// ignore
}
}
}

    /**
     * 壓縮檔案或目錄
     *
     * @param srcDirName   壓縮的根目錄
     * @param fileName     根目錄下的待壓縮的檔名或資料夾名,其中*或""表示跟目錄下的全部檔案
     * @param descFileName 目標zip檔案
     */
    public static void zipFiles(String srcDirName, String fileName, String descFileName) {
        // 判斷目錄是否存在
        if (srcDirName == null) {
        throw new RuntimeException("檔案壓縮失敗,目錄 " + srcDirName + " 不存在!");
        }
        File fileDir = new File(srcDirName);
        if (!fileDir.exists() || !fileDir.isDirectory()) {
        throw new RuntimeException("檔案壓縮失敗,目錄 " + srcDirName + " 不存在!");
        }
        String dirPath = fileDir.getAbsolutePath();
        File descFile = new File(descFileName);
        ZipOutputStream zouts = null;
        try {
            zouts = new ZipOutputStream(new FileOutputStream(descFile));
            if ("*".equals(fileName) || "".equals(fileName)) {
                zipDirectoryToZipFile(dirPath, fileDir, zouts);
            } else {
                File file = new File(fileDir, fileName);
                if (file.isFile()) {
                    zipFilesToZipFile(dirPath, file, zouts);
                } else {
                    zipDirectoryToZipFile(dirPath, file, zouts);
                }
            }            
        } catch (Exception e) {
            throw new RuntimeException("壓縮檔案失敗.",e);
        }finally{
        if(zouts != null){
        try {
zouts.close();
} catch (IOException e) {
e.printStackTrace();
}
        }
        }


    }
    
    /**
     * 解壓縮ZIP檔案,將ZIP檔案裡的內容解壓到descFileName目錄下
     *
     * @param zipFileName  需要解壓的ZIP檔案
     * @param descFileName 目標檔案
     */
    public static boolean unZipFiles(String zipFileName, String descFileName) {
        String descFileNames = descFileName;
        if (!descFileNames.endsWith(File.separator)) {
            descFileNames = descFileNames + File.separator;
        }
        InputStream is = null;
        OutputStream os = null;
        try {
            // 根據ZIP檔案建立ZipFile物件
            ZipFile zipFile = new ZipFile(zipFileName);
            ZipEntry entry = null;
            String entryName = null;
            String descFileDir = null;
            byte[] buf = new byte[4096];
            int readByte = 0;
            // 獲取ZIP檔案裡所有的entry
            @SuppressWarnings("rawtypes") Enumeration enums = zipFile.getEntries();
            // 遍歷所有entry
            while (enums.hasMoreElements()) {
                entry = (ZipEntry) enums.nextElement();
                // 獲得entry的名字
                entryName = entry.getName();
                descFileDir = descFileNames + entryName;
                if (entry.isDirectory()) {
                    // 如果entry是一個目錄,則建立目錄
                    new File(descFileDir).mkdirs();
                    continue;
                } else {
                    // 如果entry是一個檔案,則建立父目錄
                    new File(descFileDir).getParentFile().mkdirs();
                }
                File file = new File(descFileDir);
                // 開啟檔案輸出流
                os = new FileOutputStream(file);
                // 從ZipFile物件中開啟entry的輸入流
                is = zipFile.getInputStream(entry);
                while ((readByte = is.read(buf)) != -1) {
                    os.write(buf, 0, readByte);
                }
            }
            zipFile.close();
            return true;
        } catch (Exception e) {
        throw new RuntimeException("檔案解壓失敗!",e);
        } finally{
        if(is != null){
        try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
        }
        if(os != null){
        try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
        }
        }
    }


    /**
     * 上傳檔案到檔案伺服器
     * @param file
     * @return
     */
public static String upload(File file) {
String app_key = Global.getConfig("apiPicUploadKey").trim();
String app_secret = Global.getConfig("apiPicUploadSecret").trim();
Long ts = new Date().getTime();
String method = "POST";
// 拼裝字串
String MD5Str = "app_key=" + app_key + "&app_secret=" + app_secret
+ "&method=" + method + "&ts=" + ts;


// MD5字串
String sign = MD5Util.string2MD5(MD5Str.trim());
// 構建URL
String picUploadURL = servicePicUploadURL + "?app_key=" + app_key
+ "&method=" + method + "&sign=" + sign + "&ts=" + ts;
System.out.println(picUploadURL);
String fid = null;
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost(picUploadURL.trim());
FileBody f1 = new FileBody(file);
HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("f1", f1).build();
httppost.setEntity(reqEntity);
CloseableHttpResponse resp = httpclient.execute(httppost);
System.out.println(resp.getStatusLine());
for(Header head:resp.getAllHeaders()){
System.out.println(head.getName()+" : "+head.getValue());
}
HttpEntity resEntity = resp.getEntity();


System.out.println("Response content length: "
+ resEntity.getContentLength());
String ret = EntityUtils.toString(resEntity, "UTF-8");
System.out.println("返回內容:" + ret);
Map<String, Object> map = StringToMapUtil.jsonToObject(ret);
String result = (String) map.get("result");
result = result.replace("[", "").replace("]", "");
fid = (String) StringToMapUtil.jsonToObject(result).get("fid");


EntityUtils.consume(resEntity);


} catch (Exception e) {
throw new RuntimeException("上傳zip包失敗!",e);
} finally {
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return fid;
}


/**
* 獲取檔名

* @param url
* @return
*/
private static String getFileNameFromUrl(String url) {
String name = new Long(System.currentTimeMillis()).toString() + ".X";
int index = url.lastIndexOf("/");
if (index > 0) {
name = url.substring(index + 1);
if (name.trim().length() > 0) {
return name;
}
}
return name;
}


/**
* 開啟檔案輸出流

* @param file
* @param append
* @return
* @throws IOException
*/
private static FileOutputStream openOutputStream(File file, boolean append)
throws IOException {
if (file.exists()) {
if (file.isDirectory()) {
throw new IOException("File '" + file
+ "' exists but is a directory");
}
if (file.canWrite() == false) {
throw new IOException("File '" + file
+ "' cannot be written to");
}
} else {
File parent = file.getParentFile();
if (parent != null) {
if (!parent.mkdirs() && !parent.isDirectory()) {
throw new IOException("Directory '" + parent
+ "' could not be created");
}
}
}
return new FileOutputStream(file, append);
}


// copy from InputStream
// -----------------------------------------------------------------------
/**
* Copy bytes from an <code>InputStream</code> to an
* <code>OutputStream</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
* <p>
* Large streams (over 2GB) will return a bytes copied value of
* <code>-1</code> after the copy has completed since the correct number of
* bytes cannot be returned as an int. For large streams use the
* <code>copyLarge(InputStream, OutputStream)</code> method.

* @param input
*            the <code>InputStream</code> to read from
* @param output
*            the <code>OutputStream</code> to write to
* @return the number of bytes copied
* @throws NullPointerException
*             if the input or output is null
* @throws IOException
*             if an I/O error occurs
* @throws ArithmeticException
*             if the byte count is too large
* @since Commons IO 1.1
*/
private static int copy(InputStream input, OutputStream output)
throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}


/**
* Copy bytes from a large (over 2GB) <code>InputStream</code> to an
* <code>OutputStream</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.

* @param input
*            the <code>InputStream</code> to read from
* @param output
*            the <code>OutputStream</code> to write to
* @return the number of bytes copied
* @throws NullPointerException
*             if the input or output is null
* @throws IOException
*             if an I/O error occurs
* @since Commons IO 1.3
*/
private static long copyLarge(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}

    /**
     * 將目錄壓縮到ZIP輸出流
     *
     * @param dirPath 目錄路徑
     * @param fileDir 檔案資訊
     * @param zouts   輸出流
     */
    private static void zipDirectoryToZipFile(String dirPath, File fileDir, ZipOutputStream zouts) {
        if (fileDir.isDirectory()) {
            File[] files = fileDir.listFiles();
            // 空的資料夾
            if(files!=null){
            if (files.length == 0) {
                // 目錄資訊
                ZipEntry entry = new ZipEntry(getEntryName(dirPath, fileDir));
                try {

                    zouts.putNextEntry(entry);

    zouts.setEncoding("GBK"); //解決linux下中文亂碼問題,使用org.apache.tools的壓縮jar包

                    zouts.closeEntry();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return;
            }


            for (int i = 0; i < files.length; i++) {
                if (files[i].isFile()) {
                    // 如果是檔案,則呼叫檔案壓縮方法
                    zipFilesToZipFile(dirPath, files[i], zouts);
                } else {
                    // 如果是目錄,則遞迴呼叫
                    zipDirectoryToZipFile(dirPath, files[i], zouts);
                }
            }
            }
        }


    }
    /**
     * 將檔案壓縮到ZIP輸出流
     *
     * @param dirPath 目錄路徑
     * @param file    檔案
     * @param zouts   輸出流
     */
    private static void zipFilesToZipFile(String dirPath, File file, ZipOutputStream zouts) {
        FileInputStream fin = null;
        ZipEntry entry = null;
        // 建立複製緩衝區
        byte[] buf = new byte[4096];
        int readByte = 0;
        if (file.isFile()) {
            try {
                // 建立一個檔案輸入流
                fin = new FileInputStream(file);
                // 建立一個ZipEntry
                entry = new ZipEntry(getEntryName(dirPath, file));
                // 儲存資訊到壓縮檔案
                zouts.putNextEntry(entry);
                // 複製位元組到壓縮檔案
                while ((readByte = fin.read(buf)) != -1) {
                    zouts.write(buf, 0, readByte);

                }

                zouts.setEncoding("GBK"); //解決linux下中文亂碼問題,使用org.apache.tools的壓縮jar包

                zouts.closeEntry();
                //System.out.println("新增檔案 " + file.getAbsolutePath() + " 到zip檔案中!");
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
            if(fin != null){
            try{
            fin.close();
            }catch(Exception e){
            //ignore;
            }
            }
            }
        }


    }
    
    /**
     * 獲取待壓縮檔案在ZIP檔案中entry的名字,即相對於跟目錄的相對路徑名
     *
     * @param dirPat 目錄名
     * @param file   entry檔名
     * @return
     */
    private static String getEntryName(String dirPath, File file) {
        String dirPaths = dirPath;
        if (!dirPaths.endsWith(File.separator)) {
            dirPaths = dirPaths + File.separator;
        }
        String filePath = file.getAbsolutePath();
        // 對於目錄,必須在entry名字後面加上"/",表示它將以目錄項儲存
        if (file.isDirectory()) {
            filePath += "/";
        }
        int index = filePath.indexOf(dirPaths);


        return filePath.substring(index + dirPaths.length());
    }
    
    public static void main(String[] args){
    File file = new File("D:\\car-credit\\chedai_server_dev02\\2201.zip");
    upload(file);
    }
}