阿里雲物件儲存服務,OSS使用經驗總結,圖片儲存,分頁查詢
阿里雲OSS-使用經驗總結,儲存,賬號-許可權,分頁,縮圖,賬號切換
總的來說,比較簡單,但是仍然遇到了幾個問題,需要總結下。
1.OSS總的使用介紹
https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_object.html?spm=5176.docoss/api-reference/abstract.6.264.Zq5Hof
和其它各種技術類似,幫助文件常見的欄目主要是:新手指南(入門)、產品簡介、API手冊(講某個介面的用法)、SDK(API的具體化,具體到程式語言)
最佳實踐、計量付費等。
2.服務的價值
之前用過又拍雲,聽說過七牛雲端儲存。
總的來說,不同的雲廠商做得都差不多,功能總體一致,細節有所差異。
訪問量大的公司,還是最好比較下服務的細節,測試下各家的效能。
就功能來說,物件儲存的雲服務或者就統一叫做“雲端儲存”,不就是:儲存(上傳)、下載、訪問(圖片,直接在網頁中展示)、批量查詢。
周邊功能,賬戶許可權、檔案許可權等。
具體到檔案儲存,和本地Java的API,第三方的API都類似,只不過這個時候,儲存的實際物理位置在遠端伺服器上。
高階一點的說法,就是“雲”。
3.OSS和雲端儲存
雲端儲存,是一種廣泛的稱謂。
物件儲存,檔案儲存,其它儲存,則場景更加具體一些。
雲資料庫,本質還是雲端儲存,只是不是標準檔案罷了。
4.API和SDK
官方文件:https://help.aliyun.com/document_detail/oss/api-reference/abstract.html?spm=5176.docoss/sdk/java-sdk/manage_object.6.196.zg3gsg
配置賬號和密碼,建立遠端連線,執行操作,關閉連線。
太多太多的SDK,都是這麼幾步。
5.遇到的幾個問題
a.賬戶許可權
用自己的賬號,阿里雲的AccessKeyId和AccessSecret,沒有遇到任何問題。
但是,用別人給的賬號,建立bucket和批量查詢的時候,總是提示沒有許可權。
第1次遇到許可權問題的時候,還不能確認,以為是某個地方沒有配置正確。再次遇到的時候,就提交了工單,和官方的技術支援人員確定了。
不懂的問題,提交工單,阿里雲的工單服務,還是很不錯的。
問題原因:別人給的賬號密碼,是子賬戶,分配許可權不夠。
新手入門,直接使用最高許可權就好。
更深入的許可權管理,RAM和STS使用指南,可參考
https://help.aliyun.com/document_detail/oss/practice/ram_guide.html?spm=5176.docoss/api-reference/abstract.6.179.H0uY1x
b.圖片
普通的文字檔案,圖片,都是檔案,儲存方式沒啥區別。
需要注意的是,在雲端,圖片邏輯上是“目錄”儲存,實際物理層次不是,可以根據字首prefix,來模擬目錄。
圖片,可以有額外的雲服務,比如圖片縮圖、縮放、反轉、水印、防盜鏈等。
目前遇到的問題是,大尺寸的高清圖片,縮圖的寬度很小時,不夠清晰,而官網上的縮圖案例卻還比較清晰,不清楚為啥。
c.分頁訪問
官方API,是根據nextMarker(可以理解為下1頁開始的id),來分頁的,每頁最多獲得1000條。
沒有提供,一次性獲得所有圖片的介面,只能多次迭代,拿到所有的key。
在實際需要中,後端管理系統,想分頁檢視圖片列表,但是由於阿里雲的API功能有限,只能有“上一頁”和“下一頁”。
類似“1 2 3 4 5 .. 100 101”這種分頁展示方式,只能自己去實現。
我在做的時候,是通過多次迭代獲得所有圖片列表,快取到Redis中,然後手動實現分頁來做的。
6.自己封裝的程式碼
只貼自己的核心程式碼,周邊的實體類和第三方jar,不再列出。
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.PutObjectRequest;
//阿里雲物件儲存服務OSS工具
public class OssUtil {
// 演示,建立Bucket的時候,endpoint不能帶上.
// 圖片上傳和簡單的圖片訪問也可以用這個。
public static String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 圖片處理,需要用單獨的地址。訪問、裁剪、縮放、效果、水印、格式轉換等服務。
// public static String endpointImg = "http://img-cn-hangzhou.aliyuncs.com";
public static String accessKeyId = "hi";
public static String accessKeySecret = "hi";
public static String bucketName = "hi";
// 單例,只需要建立一次連結
private static OSSClient client = null;
// 是否使用另外一套本地賬戶
public static final boolean MINE = false;
static {
if (MINE) {
accessKeyId = "hi2";
accessKeySecret = "hi2";
bucketName = "hi2";
endpoint = "http://oss-cn-shanghai.aliyuncs.com";
}
}
//配置引數
static ClientConfiguration config() {
ClientConfiguration conf = new ClientConfiguration();
conf.setMaxConnections(100);
conf.setConnectionTimeout(5000);
conf.setMaxErrorRetry(3);
conf.setSocketTimeout(2000);
return conf;
}
//客戶端
public static OSSClient client() {
if (client == null) {
ClientConfiguration conf = config();
client = new OSSClient(endpoint, accessKeyId, accessKeySecret, conf);
makeBucket(client, bucketName);
}
return client;
}
//建立Bucket
public static void makeBucket(String bucketName) {
OSSClient client = client();
makeBucket(client, bucketName);
}
//建立Bucket
public static void makeBucket(OSSClient client, String bucketName) {
boolean exist = client.doesBucketExist(bucketName);
if (exist) {
p("The bucket exist.");
return;
}
client.createBucket(bucketName);
}
//上傳一個檔案,InputStream
public static void uploadFile(InputStream is, String key) {
OSSClient client = client();
PutObjectRequest putObjectRequest = new PutObjectRequest(
OssUtil.bucketName, key, is);
client.putObject(putObjectRequest);
}
//上傳一個檔案,File
public static void uploadFile(File file, String key) {
OSSClient client = client();
PutObjectRequest putObjectRequest = new PutObjectRequest(
OssUtil.bucketName, key, file);
client.putObject(putObjectRequest);
}
//下載一個檔案到本地
public static OSSObject downloadFile(String key) {
OSSClient client = client();
GetObjectRequest getObjectRequest = new GetObjectRequest(
OssUtil.bucketName, key);
OSSObject object = client.getObject(getObjectRequest);
return object;
}
//上傳某個檔案到某個目錄,key是自動生成的
public static String uploadFile(MultipartFile file, String dir)
throws IOException {
if (null != file && !file.isEmpty() && file.getSize() > 0) {
String fileName = UuidUtil.get32UUID()
+ "."
+ StringUtils.substringAfterLast(
file.getOriginalFilename(), ".");
String ymd = DateUtil.getDays();
String key = dir + ymd + "/" + fileName;
OssUtil.uploadFile(file.getInputStream(), key);
return key;
}
return null;
}
//刪除某個檔案
public static void delete(String key) {
if (BackendConst.OSS_DELTE_IMG) {
try {
client().deleteObject(OssUtil.bucketName, key);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//建立目錄,不能以斜槓“/”開頭
public static void makeDir(String keySuffixWithSlash) {
OSSClient client = client();
/*
* Create an empty folder without request body, note that the key must
* be suffixed with a slash
*/
if (StringUtils.isEmpty(keySuffixWithSlash)) {
return;
}
if (!keySuffixWithSlash.endsWith("/")) {
keySuffixWithSlash += "/";
}
client.putObject(bucketName, keySuffixWithSlash,
new ByteArrayInputStream(new byte[0]));
}
// 實時的分頁查詢
public static OssPage listPage(String dir, String nextMarker,
Integer maxKeys) {
OSSClient client = client();
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(
bucketName);
if (StringUtils.isNoneBlank(dir)) {
listObjectsRequest.setPrefix(dir);
}
if (StringUtils.isNoneBlank(nextMarker)) {
listObjectsRequest.setMarker(nextMarker);
}
if (maxKeys != null) {
listObjectsRequest.setMaxKeys(maxKeys);
}
ObjectListing objectListing = client.listObjects(listObjectsRequest);
List<OSSObjectSummary> summrayList = objectListing.getObjectSummaries();
List<OssItem> itemList = summaryToItem(summrayList);
OssPage page = new OssPage();
String newxNextMarker = objectListing.getNextMarker();
page.setNextMarker(newxNextMarker);
page.setSummrayList(itemList);
return page;
}
//把OSS的物件,轉換成自己的。因為OSS的物件沒有實現Serialiable,不能序列化。
private static List<OssItem> summaryToItem(
List<OSSObjectSummary> summrayList) {
List<OssItem> itemList = new ArrayList<OssItem>();
for (OSSObjectSummary summary : summrayList) {
OssItem item = new OssItem();
try {
BeanUtils.copyProperties(item, summary);
itemList.add(item);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return itemList;
}
//一次迭代,獲得某個目錄下的所有檔案列表
public static List<OssItem> listAll(String dir) {
OSSClient client = client();
List<OssItem> list = new ArrayList<OssItem>();
// 查詢
ObjectListing objectListing = null;
String nextMarker = null;
final int maxKeys = 1000;
do {
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(
bucketName).withPrefix(dir).withMarker(nextMarker)
.withMaxKeys(maxKeys);
objectListing = client.listObjects(listObjectsRequest);
List<OSSObjectSummary> summrayList = objectListing
.getObjectSummaries();
List<OssItem> itemList = summaryToItem(summrayList);
list.addAll(itemList);
nextMarker = objectListing.getNextMarker();
} while (objectListing.isTruncated());
return list;
}
public static void p(Object str) {
System.out.println(str);
}
public static void print(OSSException oe) {
p("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
p("Error Message: " + oe.getErrorCode());
p("Error Code: " + oe.getErrorCode());
p("Request ID: " + oe.getRequestId());
p("Host ID: " + oe.getHostId());
}
}
7.圖片展示和縮圖
展示圖片,需要使用單獨的域名
${imgDomain}/${imgUrl}@100w @100w是縮圖語法
http://b.img-cn-hangzhou.aliyuncs.com/product/xiaolei.jpg@100w
oss.properties
oss.endpoint = http://oss-cn-hangzhou.aliyuncs.com
oss.accessKeyId=hi
oss.accessKeySecret=hi
oss.bucketName=b
oss.fileDomain=http://b.oss-cn-hangzhou.aliyuncs.com
oss.imgDomain=http://b.img-cn-hangzhou.aliyuncs.com
8.小結
先去官網看文件,大概1天可以實現基礎功能。
圖片批量查詢、高階的賬戶許可權配置、圖片服務(縮圖、CDN、防盜鏈、自定義域名),稍微麻煩一點.
按道理來講,一週可以掌握絕大部分內容。
先快速瀏覽文件,把專案中最需要的先實現,更多高階功能,用到的時候,再深入研究也是不錯的。
在遇到問題的時候,網上搜尋了下,基本還沒有資料,只能去官網,實現不行,就提交工單,和權威的官方技術支援人員交流。
相關文章
- Laravel 使用阿里雲 oss 儲存物件Laravel阿里物件
- 使用java開發阿里雲OSS開放雲端儲存服務Java阿里
- 阿里雲物件儲存OSS支援版本管理特性阿里物件
- Oracle服務啟動-索引-子查詢-分頁儲存過程問題Oracle索引儲存過程
- 阿里雲物件儲存OSS及CDN加速配置阿里物件
- Unirech:阿里雲國際站的物件儲存oss與自建儲存的區別阿里物件
- 物件儲存服務的完整性檢查物件
- 使用MinIO搭建物件儲存服務物件
- 儲存圖片
- 物件儲存服務的Lambda特性物件
- 物件儲存服務的加密特性物件加密
- OSS物件儲存的全球加速方案物件
- .Net之使用Jquery Ajax通過FormData物件非同步提交圖片檔案到服務端儲存並返回儲存的圖片路徑jQueryORM物件非同步服務端
- 資料庫儲存選型經驗總結資料庫
- 可用。儲存分頁
- Delphi儲存網頁中的圖片網頁
- 海量圖片儲存,杉巖分散式物件儲存輕鬆應對分散式物件
- Activiti 儲存圖片
- 物件儲存服務(Object Storage Service,OBS)物件Object
- QingStor 物件儲存服務正式商用物件
- 物件儲存服務的事件通知特性物件事件
- 物件儲存服務OBS obsfs掛載物件
- 物件儲存服務的壓縮特性物件
- 使用七牛雲端儲存的一些經驗總結
- 使用JavaScript將當前頁面儲存成PDF,支援圖片和文字的儲存JavaScript
- oss-server 小型物件儲存系統Server物件
- 阿里雲OSS雲端儲存管理實踐阿里
- 塊儲存 檔案儲存 物件儲存物件
- 物件儲存服務與圖片伺服器的優缺點對比物件伺服器
- Oracle查詢結果 儲存為XMLOracleXML
- 儲存—物件儲存_Minio物件
- 華為雲學院乾貨:物件儲存服務:便捷管理儲存資源物件
- 華為雲OBS物件儲存服務:值得擁有的貼心的儲存管家物件
- Sql儲存過程分頁--臨時表儲存SQL儲存過程
- SQL Server 2000 的分頁查詢(儲存過程)SQLServer儲存過程
- 【答疑】物件儲存OSS常見問題解答(諮詢類2)物件
- 【答疑】物件儲存OSS常見問題解答(諮詢類1)物件
- 分頁儲存過程儲存過程