前言
毫无目标的生活会导致自我的放纵,滋生懒惰。
只有被追赶着才能进步,谁在追赶着你?来自生活中的讽刺?还是自我的鞭挞?
工作之余,学点新东西还是不错的,七牛云存储一个很不错的云产品。
一、简介
七牛云存储:静态资源云端存储。产品主要面对的是开发者、企业用户,你可以把自己的项目、网站中的图片、文档、音频、视频等静态的资源存储在云端,还提供其他服务,比如视频音频转码,图片简单处理等。
点击七牛云存储注册,注册后首先是体验用户,身份认证后变成标准用户,区别如下:
功能特性 | 体验用户 | 标准用户 |
---|---|---|
验证 | 邮箱验证 | 手机+邮箱+身份认证 |
额度限制 | 免费存储空间1G 免费每月下载流量1G 免费每月GET请求10万次 免费每月PUT/DELETE请求1万次 |
免费存储空间10G 免费每月下载流量10G 免费每月GET请求100万次 免费每月PUT/DELETE请求10万次 |
空间数量 | 1 | 20 |
空间访问控制 | 可修改 | 不可修改 |
内容限制 | 富媒体 | 不限制 |
FOP | imageFop | all |
自定义域名 | 无 | 账户余额大于10元可用 |
防盗链 | 无 | 账户余额大于10元可用 |
https | 无 | 可用 |
镜像存储 | 镜像富媒体 | 可用 |
访问日志 | 无 | 可用 |
抵用券 | 无 | 可用 |
账户冻结 | 实时冻结 | 50元>N,连续欠费30个自然日后冻结; 500元>N>50元,连续欠费3个自然日后冻结; N>500元,实时冻结。* |
*N表示账户余额。
二、Java API使用
七牛云存储用户可以有多个表空间,每个表空间相当于一个磁盘分区,分为共有的和私有的,所有的数据都是以<key,hashcode>的方式进行存储的,没有文件夹这一说法。当然你可以通过给文件加前缀来模拟文件夹,比如 “文档/公司/2.png”
去七牛云存储下载java版的SDK(现在已经有很多语言的API了),在SDK中的Config类中进行配置:
//bucket public static final String BUCKETNAME="qiniuinas"; //域名地址 public static final String DOMAIL="qiniuinas.qiniudn.com"; public static String ACCESS_KEY = "****************************************"; public static String SECRET_KEY = "****************************************";
BUCKETNAME和DOMAIL是我自己加上去的,方便调用和配置,BUCKETNAME为表空间名称,DOMAIL为域名。
ACCESS_KEY和SECRET_KEY为你注册后的密钥。
个人写的工具类:
package com.inas.qiniu; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.qiniu.api.auth.digest.Mac; import com.qiniu.api.config.Config; import com.qiniu.api.fop.ImageView; import com.qiniu.api.io.IoApi; import com.qiniu.api.io.PutExtra; import com.qiniu.api.io.PutRet; import com.qiniu.api.net.CallRet; import com.qiniu.api.rs.BatchCallRet; import com.qiniu.api.rs.BatchStatRet; import com.qiniu.api.rs.Entry; import com.qiniu.api.rs.EntryPath; import com.qiniu.api.rs.GetPolicy; import com.qiniu.api.rs.PutPolicy; import com.qiniu.api.rs.RSClient; import com.qiniu.api.rs.URLUtils; import com.qiniu.api.rsf.ListItem; import com.qiniu.api.rsf.ListPrefixRet; import com.qiniu.api.rsf.RSFClient; import com.qiniu.api.rsf.RSFEofException; /** * @project: * * @author: inas * * @creatDate: 2014-11-07 * * @discrible: 七牛工具类 * * @other: */ public class QiniuUtils { /** * delete : 根据文件名删除文件 * @param key 文件名 * @return 200:成功 * 612:没有文件 * 631:没有bucket */ public static int delete(String key) { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); RSClient client = new RSClient(mac); CallRet ret=client.delete(Config.BUCKETNAME, key); return ret.getStatusCode(); } /** * BatchDelete : 批量删除 * @param listKey 文件名列表 * @return null: 删除成功 * map: 部分删除失败 <文件名,删除结果> */ public static Map<String, Integer> BatchDelete(List<String> listKey) { EntryPath entryPath=null; Map<String, Integer> map=new HashMap<String, Integer>(); Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); RSClient rs = new RSClient(mac); List<EntryPath> entries = new ArrayList<EntryPath>(); for(String key:listKey) { entryPath=new EntryPath(); entryPath.bucket=Config.BUCKETNAME; entryPath.key=key; entries.add(entryPath); } BatchCallRet bret = rs.batchDelete(entries); if(bret.ok()) { return null; } else { for(int i=0;i<listKey.size();i++) { map.put(listKey.get(i), bret.results.get(i).statusCode); } return map; } } /** * deletePiefix : 删除带有指定前缀的文件 * @param piefix * @return */ public static Map<String, Integer> deletePiefix(String piefix) { List<String> keyList=new ArrayList<String>(); List<ListItem> statList=getListStatByPrefix(piefix); for(ListItem li:statList) { keyList.add(li.key); } return BatchDelete(keyList); } /** * getFileStat : 获取单个文件的详细信息 * @param key 文件名称 * @return Entry 实体 */ public static Entry getStat(String key) { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); RSClient client = new RSClient(mac); Entry statRet = client.stat(Config.BUCKETNAME, key); return statRet; } /** * getListStat : 获取多个文件的文件信息 * @param listKey 文件列表 * @return BatchStatRet 文件信息 */ public static BatchStatRet getListStat(List<String> listKey) { EntryPath entryPath=null; Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); RSClient rs = new RSClient(mac); List<EntryPath> entries = new ArrayList<EntryPath>(); for(String key:listKey) { entryPath=new EntryPath(); entryPath.bucket=Config.BUCKETNAME; entryPath.key=key; entries.add(entryPath); } BatchStatRet bret = rs.batchStat(entries); return bret; } /** * getListStatByPrefix : 获取指定前缀的文件列表(pix 为"" 获取所有文件信息) * @param listKey * @param pix * @return */ public static List<ListItem> getListStatByPrefix(String pix) { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); RSFClient client = new RSFClient(mac); String marker = ""; List<ListItem> all = new ArrayList<ListItem>(); ListPrefixRet ret = null; while (true) { ret = client.listPrifix(Config.BUCKETNAME, pix, marker,1000); //1000获取的条数限制,最多1000条 marker = ret.marker; all.addAll(ret.results); if (!ret.ok()) { break; } } if (ret.exception.getClass() != RSFEofException.class) { return null; } return all; } /** * getListStatByPrefix : 模糊搜索文件 * @param key * @return */ public static Map<String, Integer> getListByName(String key) { return null; } /** * download : 根据文件名获取文件下载链接(私有) * @param key * @return * @throws Exception */ public static String download(String key) throws Exception { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); String baseUrl = URLUtils.makeBaseUrl(Config.DOMAIL, key); GetPolicy getPolicy = new GetPolicy(); return getPolicy.makeRequest(baseUrl, mac); } /** * download :根据域名和文件名获取文件下载地址(共有) * @param domain 域名 * @param key 文件名 * @return 下载URL */ public static String download(String domain,String key) { return "http://"+domain+"/"+key; } /** * downloadList : 批量获取文件下载地址 * @param listKey 文件名列表 * @return map<文件名,文件下载地址> * @throws Exception */ public static Map<String, String> downloadList(List<String> listKey) throws Exception { Map<String, String> map=new HashMap<String, String>(); for(int i=0;i<listKey.size();i++) { map.put(listKey.get(i), download(listKey.get(i))); } return map; } /** * upload : 上传文件 * @param localFile 本地文件地址 * @param key 文件名 * @return 200:成功 * 612:没有文件 * 631:没有bucket */ public static int upload(String localFile,String key) throws Exception { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); PutPolicy putPolicy = new PutPolicy(Config.BUCKETNAME); String uptoken = putPolicy.token(mac); PutExtra extra = new PutExtra(); PutRet ret = IoApi.putFile(uptoken, key, localFile, extra); return ret.getStatusCode(); } /** * copy :文件复制 * @param bucketFrom 表空间名称 * @param keyFrom 文件名 * @param buckeTo 表空间名称 * @param keyTo 文件名 * @return 200:成功 * 612:没有文件 * 631:没有bucket */ public static int copy(String bucketFrom,String keyFrom,String buckeTo,String keyTo) { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); RSClient client = new RSClient(mac); CallRet ret=client.copy(bucketFrom, keyFrom, buckeTo, keyTo); return ret.getStatusCode(); } /** * move :文件移动 * @param bucketFrom 表空间名称 * @param keyFrom 文件名 * @param buckeTo 表空间名称 * @param keyTo 文件名 * @return 200:成功 * 612:没有文件 * 631:没有bucket */ public static int move(String bucketFrom,String keyFrom,String buckeTo,String keyTo) { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); RSClient client = new RSClient(mac); CallRet ret=client.move(bucketFrom, keyFrom, buckeTo, keyTo); return ret.getStatusCode(); } /** * fopImageView : 生成图片预览地址 * @param domain 域名 * @param key 文件名 * @return url地址 * @throws Exception */ public static String fopImageView(String domain,String key) throws Exception { Mac mac = new Mac(Config.ACCESS_KEY, Config.SECRET_KEY); String url = "http://"+domain+ "/" + key; ImageView iv = new ImageView(); iv.mode = 1 ; iv.width = 100 ; iv.height = 200 ; iv.quality = 1 ; iv.format = "png" ; String viewUrl = iv.makeRequest(url); viewUrl = new GetPolicy().makeRequest(viewUrl, mac); return viewUrl; } }
三、七牛云存储server返回结果说明
服务器返回结果的基类是 CallRet 即返回结果
属性: statusCode 执行状态标识
* 200:成功
* 612:没有文件* 631:没有表空间
* 401:下载token认证失败
response:返回的结果
exception: 返回的异常
方法: ok() :是否操作成功
以下方法都继承CallRet 方法:
BatchCallRet: List<Callret>
Entry :附加了一些文件的属性
BatchStatRet :List<Entry >
ListPrefixRet :附加了前缀属性
PutRet:上传返回结果
以上只是简单的说明,更详细的查看API文档里面每个方法的详细定义,理解肯定更深刻。
总结
七牛云存储对于开发者来说还是不错的,只需要在项目中封装好一个jar包就可以很简单的把一些静态资源存储在云端,对于个人开发的产品或者一些企业产品,免费的标准用户的资源已经足够了使用了。java sdk很多的地方还不够完善。