使用java開發阿里雲OSS開放雲端儲存服務

業餘草發表於2017-02-15

購買了阿里雲後,我們發現一般ECS的儲存空間都比較小,當然我們可以動態的擴充套件一些儲存空間。但是作為開發者,我們在日常使用中需要一些更大的靈活性,因此就需要我們自己對OSS儲存有一些自己的擴充套件。今天就為大家分享一下如何使用java來對接阿里雲的OSS儲存服務。

OSS產品概述

阿里雲物件儲存服務(Object Storage Service,簡稱 OSS),是阿里雲提供的海量、安全、低成本、高可靠的雲端儲存服務。您可以通過呼叫 API,在任何應用、任何時間、任何地點上傳和下載資料,也可以通過 Web 控制檯對資料進行簡單的管理。OSS 適合存放任意型別的檔案,適合各種網站、開發企業及開發者使用。

開通阿里雲OSS服務

首先要登入阿里雲官網,然後選擇產品——>儲存於CDN——>物件儲存 OSS。如下圖:


然後我們可以根據自己的情況進行開通。開通完成後,我們就可以進入OSS控制檯了。

OSS 控制檯

OSS控制檯佈局包括bucket列表,bucket所在地域,建立時間和對於bucket操作。bucket這個概念用比較通俗的說法,就是使用者建立的頂層目錄,所有使用者上傳的檔案都必須存在bucket下面,而且bucket在OSS系統中是不能重名的。如果已經有一個使用者建立了bucket名稱叫abc,那麼很遺憾,您就不能建立一個名稱叫abc的bucket了,每個使用者可以建立10個bucket。注意紅圈標註的ACCESSKEY管理按鈕,點選後可以進行ACCESSKEY管理介面。


進入後點選顯示,可以看到祕鑰,AccesskeyId&AccessKeySecret 的使用方法請見OSS API文件
點選具體bucket,進入bucket 管理功能,包括bucket屬性設定、object管理等。


建立Bucket

如果你還沒有建立bucket,點選新建bucket。


進入新建Bucket頁面,並填寫Bucket資訊


填寫Bucket名稱,選擇所屬地域,設定讀寫許可權。 在填寫完bucket資訊後點選提交,建立bucket。

上傳檔案

點選紅圈標註的上傳檔案,會彈出檔案框列表,選擇需要上傳的檔案進行上傳。


分享檔案

點選對應檔案的獲取地址,會彈出一個object 地址資訊,其中地址連結可以是在公網訪問到的。別人點選這個連結就可以下載到這個檔案了,但是親這可是要注意會產生流量費用的。


注意:如你的OSS Bucket未繫結域名,則你訪問檔案連結後預設為下載該檔案,而不能直接瀏覽該檔案。

java開發OSS儲存服務

開通OSS伺服器後,會有endpoint,跟地址;accessKeyId,類似使用者名稱;accessKeySecret,類似密碼;buketName:第一層資料夾的名字,一個使用者可以建立十個bucketName,類似於我們的C,D,E,F碟符;accessUrl,很明顯使用者可以通過瀏覽器訪問的地址。例如我們上傳一個html檔案,我們就可以通過"accessUrl/bucketName/目錄/檔名.html,來進行訪問。我在這裡負責一個是頁面靜態化的功能,將動態的JSP頁面生成靜態的html頁面,然後上傳的OSS伺服器,返回地址,讓使用者直接訪問靜態頁面,這樣就大大加快訪問的速度。
OSS資訊實體類,OSSConfigure.Java:
import java.io.IOException;
import java.util.Properties;

public class OSSConfigure {

	private String endpoint;
	private String accessKeyId;
	private String accessKeySecret;
	private String bucketName;
	private String accessUrl;

	public OSSConfigure() {

	}

	/**
	 * 通過配置檔案.properties檔案獲取,這幾項內容。
	 * @param storageConfName
	 * @throws IOException
	 */
	public OSSConfigure(String storageConfName) throws IOException {

		Properties prop = new Properties();
		prop.load(this.getClass().getClassLoader()
				.getResourceAsStream("conf/" + storageConfName));

		endpoint = prop.getProperty("endpoint").trim();
		accessKeyId = prop.getProperty("accessKeyId").trim();
		accessKeySecret = prop.getProperty("accessKeySecret").trim();
		bucketName = prop.getProperty("bucketName").trim();
		accessUrl = prop.getProperty("accessUrl").trim();

	}

	public OSSConfigure(String endpoint, String accessKeyId,
			String accessKeySecret, String bucketName, String accessUrl) {

		this.endpoint = endpoint;
		this.accessKeyId = accessKeyId;
		this.accessKeySecret = accessKeySecret;
		this.bucketName = bucketName;
		this.accessUrl = accessUrl;
	}

	public String getEndpoint() {
		return endpoint;
	}

	public void setEndpoint(String endpoint) {
		this.endpoint = endpoint;
	}

	public String getAccessKeyId() {
		return accessKeyId;
	}

	public void setAccessKeyId(String accessKeyId) {
		this.accessKeyId = accessKeyId;
	}

	public String getAccessKeySecret() {
		return accessKeySecret;
	}

	public void setAccessKeySecret(String accessKeySecret) {
		this.accessKeySecret = accessKeySecret;
	}

	public String getBucketName() {
		return bucketName;
	}

	public void setBucketName(String bucketName) {
		this.bucketName = bucketName;
	}

	public String getAccessUrl() {
		return accessUrl;
	}

	public void setAccessUrl(String accessUrl) {
		this.accessUrl = accessUrl;
	}

}
然後再建立一個工具類,這裡需要提出的OSS伺服器,上所有的都是物件,沒有資料夾的概念,上傳檔案,直接寫好路勁,他會自動建立。這裡有一個入口OSSClient,很多方法都是通過它來實現的。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;

/**
 * 對OSS伺服器進行上傳刪除等的處理
 *
 */
public class OSSManageUtil {
	/**
	 * 上傳OSS伺服器檔案
	* @Title: uploadFile 
	* @Description: 
	* @param @param ossConfigure
	* @param @param file
	* @param @param remotePath
	* @param @return
	* @param @throws Exception    設定檔案 
	* @return String    返回型別 
	* @throws
	 */
	public static String uploadFile(OSSConfigure ossConfigure,File file,String remotePath) throws Exception{
		InputStream fileContent=null;
		fileContent=new FileInputStream(file);
		
		OSSClient ossClient=new OSSClient(ossConfigure.getEndpoint(), ossConfigure.getAccessKeyId(), ossConfigure.getAccessKeySecret());
		 String remoteFilePath = remotePath.substring(0, remotePath.length()).replaceAll("\\\\","/")+"/";
		//建立上傳Object的Metadata
		ObjectMetadata objectMetadata=new ObjectMetadata();
		objectMetadata.setContentLength(fileContent.available());
		objectMetadata.setCacheControl("no-cache");
		objectMetadata.setHeader("Pragma", "no-cache");
		objectMetadata.setContentType(contentType(file.getName().substring(file.getName().lastIndexOf("."))));
		objectMetadata.setContentDisposition("inline;filename=" + file.getName());
		//上傳檔案
		ossClient.putObject(ossConfigure.getBucketName(), remoteFilePath + file.getName(), fileContent, objectMetadata);
		System.out.println(ossConfigure.getAccessUrl()+"/" +remoteFilePath + file.getName());
		return ossConfigure.getAccessUrl()+"/" +remoteFilePath + file.getName();
	}
	
	
	/**
	 * 根據key刪除OSS伺服器上的檔案
	* @Title: deleteFile 
	* @Description: 
	* @param @param ossConfigure
	* @param @param filePath    設定檔案 
	* @return void    返回型別 
	* @throws
	 */
	public static void deleteFile(OSSConfigure ossConfigure,String filePath){
		OSSClient ossClient = new OSSClient(ossConfigure.getEndpoint(),ossConfigure.getAccessKeyId(), ossConfigure.getAccessKeySecret());
		ossClient.deleteObject(ossConfigure.getBucketName(), filePath);
		
	}
	
   /**
     * Description: 判斷OSS服務檔案上傳時檔案的contentType
     * @Version1.0
     * @param FilenameExtension 檔案字尾
     * @return String 
     */
	 public static String contentType(String FilenameExtension){
		if(FilenameExtension.equals("BMP")||FilenameExtension.equals("bmp")){return "image/bmp";}
		if(FilenameExtension.equals("GIF")||FilenameExtension.equals("gif")){return "image/gif";}
		if(FilenameExtension.equals("JPEG")||FilenameExtension.equals("jpeg")||
		   FilenameExtension.equals("JPG")||FilenameExtension.equals("jpg")||	
		   FilenameExtension.equals("PNG")||FilenameExtension.equals("png")){return "image/jpeg";}
		if(FilenameExtension.equals("HTML")||FilenameExtension.equals("html")){return "text/html";}
		if(FilenameExtension.equals("TXT")||FilenameExtension.equals("txt")){return "text/plain";}
		if(FilenameExtension.equals("VSD")||FilenameExtension.equals("vsd")){return "application/vnd.visio";}
		if(FilenameExtension.equals("PPTX")||FilenameExtension.equals("pptx")||
			FilenameExtension.equals("PPT")||FilenameExtension.equals("ppt")){return "application/vnd.ms-powerpoint";}
		if(FilenameExtension.equals("DOCX")||FilenameExtension.equals("docx")||
			FilenameExtension.equals("DOC")||FilenameExtension.equals("doc")){return "application/msword";}
		if(FilenameExtension.equals("XML")||FilenameExtension.equals("xml")){return "text/xml";}
		return "text/html";
	 }
}
好了,到這裡OSS的簡單開發就已經完成了。由於時間關係,我這裡就寫到這裡,萬事開頭難,你對OSS有了簡單的認識後。官網剩下的一堆api對你來說都是小菜。下面我在說一下在使用過程中遇到的問題和解決方案。

使用OSS儲存服務遇到的問題和解決方案

ECS伺服器被清洗

當伺服器流量達到使用者雲盾設定的清洗閾值時,會自動進入流量清洗。
請注意,由於安全策略無法做到100%識別請求是否惡意,所以伺服器被清洗後可能會有低概率的誤殺存在,但絕大部分情況下正常請求不會受到影響,如果懷疑有誤殺可提交工單由售後支援協助判斷。

不同帳號下ECS伺服器內網不通

預設情況下,不同帳號下的伺服器內網是不通的。如果使用者同時有多個帳號,並且多個帳號下都有伺服器,那麼這些伺服器內網是不通的。如果需要不同帳號下內網互通,需要提交工單聯絡售後,阿里雲售後工程師會協助打通內網。
請注意,需要內網打通的不同的帳號需要全部提交工單,說明哪些IP和哪些IP進行內網互通,或者帳號下所有伺服器內網互通。並且在每一個工單中,都把已經提交的內網互通的工單號列出來(自身的工單號除外),以便阿里雲售後工程師進行安全驗證。

OSS記憶體洩漏

如果你遇到OSS記憶體洩漏問題,首先檢查檢查你的程式碼,肯定是某些該關閉IO流沒有關閉。如果不能及時解決,可以提交工單,聯絡客服。

oss的callback返回的資料格式非JSON格式

可能是應用伺服器處理過程中拋了異常,導致沒有按照預期返回給OSS,而是返回了一些棧資訊等,就可能會導致非JSON格式的資料產生。

OSS 返回的狀態不為200

400或者其他的status比如404/403等是指應用伺服器返回給oss的http是400或者404/403等,正常情況下應用伺服器必須返回200給OSS。502是由於應用伺服器根本就沒有起web服務,沒有監聽OSS發過來的回撥請求。

相關文章