1. 程式人生 > >JAVA-阿里雲OSS檔案下載並將檔案壓縮為ZIP格式儲存

JAVA-阿里雲OSS檔案下載並將檔案壓縮為ZIP格式儲存

一,引言

由於公司業務功能需求,需要從阿里雲OSS(Object Storage Service,物件儲存服務)中獲取檔案並打壓縮成ZIP格式,在這次開發中使用了OSS檔案下載相關服務,檔案壓縮功能使用的是commons-compress-x.x.jar中提供的功能。

二,服務建立,jar包引入

(1)jar包方式匯入

OSS jar包下載 : aliyun-sdk-oss-2.8.3.zip(百度網盤) /  OSS官方網站,下載java SDK開發包後,解壓該壓縮包,將解壓後文件夾中的aliyun-sdk-oss-2.8.3.jar 以及lib資料夾中的所有檔案匯入到專案中(Eclipse:選中專案-->File-->Project Structure-->Modules-->Dependencies--> + -->JARs or directories --->將上述解壓中所描述的所有jar,匯入到 External Libraries中)

(IDEA:選中專案-->File-->-->Project Structure --> Modules --Dependencies --> + --> JARs or directories--->將所需jar匯入到External Libraries中)

IDEA:

1.專案---> File --> Project Structure

 2.Modules-->專案-->Dependencies--> + JARs or directories

3.選擇jar包

(2)pom引入

OSS:

    <!--oss-->
	<dependency>
		<groupId>com.aliyun.oss</groupId>
		<artifactId>aliyun-sdk-oss</artifactId>
		<version>2.8.3</version>
	</dependency>

commons-compress:(檔案壓縮)

<!--檔案壓縮-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-compress</artifactId>
	<version>1.14</version>
</dependency>


<!--操作檔案所需-->
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.4</version>
</dependency>

三,程式碼實現

本次我使用maven工程,使用springboot框架(自己測試時,挑自己喜歡的模式開發即可),引入springboot基本pom依賴和以上pom依賴,就可以開始開發了。

package com.test.oss.osstest.Util;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.GetObjectRequest;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.FileUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 將OSS檔案下載到本地並打包成zip格式儲存
 */
@RestController
public class FileOSSZIPUtil {
    /**
     * 從OSS服務中下載所需檔案到本地臨時檔案
     * @param endponit oss對外服務的域名
     * @param accessKeyId 使用者身份認證標識
     * @param accessKeySecret 用於加密簽名字串,oss用來驗證簽名字串的祕鑰
     * @param bucketName 要訪問的儲存空間
     * @param objectNames 要下載的物件/檔案
     * @return
     */
    private static String downloadOSS(String endponit, String accessKeyId, String accessKeySecret, String bucketName, List<String> objectNames){
        String basePath="src/main/resources/files";
        OSSClient ossClient = null;
        try{
            //建立OSSClient例項,用於操作oss空間
            ossClient = new OSSClient(endponit, accessKeyId, accessKeySecret);
            for (String objectName:objectNames){
                //指定檔案儲存路徑
                String filePath = basePath+"/"+objectName.substring(0,objectName.lastIndexOf("/"));
                //判斷檔案目錄是否存在,不存在則建立
                File file = new File(filePath);
                if (!file.exists()){
                    file.mkdirs();
                }
                //判斷儲存檔名是否加字尾
                if (objectName.contains(".")){
                    //指定檔案儲存名稱
                    filePath = filePath+"/"+objectName.substring(objectName.lastIndexOf("/")+1);
                }

                //獲取OSS檔案並儲存到本地指定路徑中,此檔案路徑一定要存在,若儲存目錄不存在則報錯,若儲存檔名已存在則覆蓋本地檔案
                ossClient.getObject(new GetObjectRequest(bucketName,objectName),new File(filePath));
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }finally {
            //關閉oss連線
            if (ossClient != null){
                ossClient.shutdown();
            }
        }
        return basePath;
    }

    /**
     * 從OSS服務中下載所需檔案到本地臨時檔案,並將檔案以ZIP格式進行壓縮
     * @param endpoint oss對外服務的域名
     * @param accessKeyId 使用者身份認證標識
     * @param accessKeySecret 用於加密簽名字串,oss用來驗證簽名字串的祕鑰
     * @param bucketName 要訪問的儲存空間
     * @param objectNames 要下載的物件/檔案
     * @param zipName zip檔名
     * @throws Exception
     */
    @RequestMapping("/oss_zip")
    public static void fileToZip(String endpoint,String accessKeyId,String accessKeySecret,String bucketName,List<String> objectNames,String zipName) throws Exception {
        File file = null;
        try{
            //呼叫方法貨物OSS中的檔案
            String fileName = downloadOSS(endpoint, accessKeyId, accessKeySecret, bucketName, objectNames);
            //獲取待壓縮檔案源
            file = new File(fileName);
            //指定壓縮檔案存放路徑
            String  zipFileName = "src/main/resources/zipFiles/"+zipName+".zip";
            File zipFile = new File(zipFileName);
            //構建輸出流
            FileOutputStream fout = new FileOutputStream(zipFile);
            //構建壓縮輸出流
            ArchiveOutputStream aos = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, fout);
            //判斷獲取的壓縮例項是否為zip格式
            if (aos instanceof ZipArchiveOutputStream){
                //進行壓縮例項強轉
                ZipArchiveOutputStream zipos = (ZipArchiveOutputStream) aos;

                //將指定檔案封裝成壓縮項,新增到壓縮流中
                //判斷檔案是否存在
                if (file.exists()){
                    //判斷檔案型別,呼叫檔案處理方法
                    zipDir(zipos,file,"");
                }
            }
            //關閉流
            aos.flush();
            aos.close();
        }catch (Exception e){
            System.out.println(e.getMessage());
            e.printStackTrace();
        }finally {
            //刪除檔案源,只保留zip檔案
            if (file.exists()){
                //判斷檔案型別
                if(file.isDirectory()){
                    //對資料夾進行處理遞迴刪除(有內容的資料夾不能直接被刪除)
                    deleteFile(file);
                    file.delete();//刪除空資料夾
                }else {
                    file.delete();//檔案直接刪除
                }
            }
        }
    }

    /**
     * 對壓縮資料夾進行迴圈處理
     * @param zipos 壓縮流
     * @param file 要處理的檔案
     * @param baseDir 要處理的檔案的資料夾路徑
     * @throws IOException
     */
    private static void zipDir(ZipArchiveOutputStream zipos,File file,String baseDir) throws IOException {
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (File f:files){
                //對檔案進行遞迴判斷
                zipDir(zipos,f,baseDir+file.getName()+File.separator);
            }
        }else{
            //將檔案封裝成壓縮項
            //根據檔案建立zip內容實體
            ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file,baseDir+file.getName());
            //將根據檔案建立的實體儲存到壓縮流中
            zipos.putArchiveEntry(zipArchiveEntry);
            //將內容輸出到壓縮檔案中
            zipos.write(FileUtils.readFileToByteArray(file));
            zipos.closeArchiveEntry();
        }
    }

    /**
     * 檔案及資料夾的遞迴刪除
     * @param file
     */
    private static void deleteFile(File file){
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (File f: files){
                deleteFile(f);
                //將迴圈後的空資料夾刪除
                if(f.exists()){
                    f.delete();
                }
            }
        }else{
            file.delete();
        }
    }

    public static void main(String[] args) {
        ArrayList<String> fileNames = new ArrayList<>();
        //oss的儲存空間內部是扁平的,沒有檔案系統目錄概念,所有的物件都隸屬於其對應的儲存空間,在下載是必須明確的指出要下在的檔案,指定其上層(檔案系統概念)資料夾,無法下載其內部檔案
        //fileNames.add("image1/"); //WARN com.aliyun.oss - Cannot read object content stream: src\main\resources\files\image1 (拒絕訪問。)
        fileNames.add("image1/image2/2.jpg");
        fileNames.add("image1/image2/3.jpg");
        fileNames.add("image1/0.jpg");
        try {
            //此連線OSS資源為本人OSS服務資源,可供學習人員進行下載測試,請勿做它用
            fileToZip("http://oss-cn-qingdao.aliyuncs.com","LTAIUkHILUDTpU5y","PNNHBr28k1xBjOMxzdKBzsvdIjsnWB","first-test-syy",fileNames,"testImage");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

補充:java - OSS下載檔案方式(下載到本地 , 流式下載) 更多:官網

package com.test.oss.osstest.Util;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;

import java.io.*;

/**
 * 將oss伺服器中的檔案下載到本地檔案中
 */
public class FileOSSUtil {
    /**
     * 下載檔案到本地
     * @param endpoint
     * @param asseccKeyId
     * @param asseccKeySecret
     * @param bucketName
     * @param objectName
     */
    public static void ossToLocal(String endpoint,String asseccKeyId,String asseccKeySecret,String bucketName,String objectName){
        //構建OSSClient例項,用來操作OSS
        OSSClient ossClient = new OSSClient(endpoint, asseccKeyId, asseccKeySecret);

        //下載OSS檔案到本地
        ossClient.getObject(new GetObjectRequest(bucketName,objectName),new File("g:/a.zip"));

        //關閉連線
        ossClient.shutdown();
    }

    /**
     * OSS流式下載,當下載檔案過大或一次性下載耗時過長,可以選擇流式下載,
     * 一次只處理部分內容,直到檔案下載完成
     * @param endpoint
     * @param asseccKeyId
     * @param asseccKeySecret
     * @param bucketName
     * @param objectName
     */
    public static  void ossToStream(String endpoint,String asseccKeyId,String asseccKeySecret,String bucketName,String objectName) throws IOException {
        //建立OSSClient
        OSSClient ossClient = new OSSClient(endpoint, asseccKeyId, asseccKeySecret);

        //呼叫ossClient.getObject(bucketName,objectName)方法獲取檔案物件(OSSObject),其中包含儲存空間名稱,檔名稱,檔案元資訊及一個輸入流
        OSSObject ossobject = ossClient.getObject(bucketName, objectName);
        //ossobject.getKey();//物件(檔案)名

        //獲取ossobject中的輸入流,讀取檔案內容
        InputStream ois = ossobject.getObjectContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(ois));
        while (true) {
            String line = reader.readLine();
            if (line == null) break;
            System.out.println("\n" + line);
        }
        // 資料讀取完成後,獲取的流必須關閉,否則會造成連線洩漏,導致請求無連線可用,程式無法正常工作。
        reader.close();
        // 關閉OSSClient。
        ossClient.shutdown();
    }

    public static void main(String[] args) throws IOException {

        //ossToLocal("http://oss-cn-qingdao.aliyuncs.com","LTAIUkHILUDTpU5y","PNNHBr28k1xBjOMxzdKBzsvdIjsnWB","first-test-syy","test/syy/random_awards.zip");
        ossToStream("http://oss-cn-qingdao.aliyuncs.com","LTAIUkHILUDTpU5y","PNNHBr28k1xBjOMxzdKBzsvdIjsnWB","first-test-syy","test/test.txt");

    }
}

欄位簡介:

bucketName:儲存空間(Bucket)名稱,儲存空間是用於儲存物件(檔案)的容器,所有的物件(檔案)都必須隸屬於某個儲存空間。

objectName: 下載的物件(檔案)名,物件(Object/檔案)是OSS儲存資料的基本單元,也成為OSS的檔案,物件有元資訊(Object Meta),使用者資料 和 檔名(Key)組成,物件由儲存空間內部唯一的key(檔名)來標識。

endpoint:Endpoint 是OSS對外服務的訪問域名

AccessKey: 訪問祕鑰,accessKeyId 和 accessKeySecret用來連線OSS時做身份驗證

最後獻上程式碼一份下載後可直接使用測試(所寫測試方法均在所在類的main方法中):oss-test

本次使用總結完畢,更多內容且看下次總結。