阿里云对象存储服务,OSS使用经验总结,图片存储,分页查询

阿里云OSS-使用经验总结,存储,帐号-权限,分页,缩略图,帐号切换html


最近项目中,须要使用云存储,最后选择了阿里云-对象存储服务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、防盗链、自定义域名),稍微麻烦一点.   按道理来说,一周能够掌握绝大部份内容。   先快速浏览文档,把项目中最须要的先实现,更多高端功能,用到的时候,再深刻研究也是不错的。      在遇到问题的时候,网上搜索了下,基本尚未资料,只能去官网,实现不行,就提交工单,和权威的官方技术支持人员交流。
相关文章
相关标签/搜索