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
本次使用總結完畢,更多內容且看下次總結。