七牛云图片存储Java篇
一 【程序员头痛的问题】
1 . 海量存储 在互联网的应用中,用户会上传大量的图片以及文件,而且访问频繁,如果文件都以传统方式存在服务器磁盘上(单节点),对CPU,内存,磁盘空间和网络带宽等服务器资源都是很大的挑战。主要体现在:
- 单节访问,并发问题 
- 单节点存储,单点故障 
- 访问权限控制 
- 扩容(水平扩展) 
2 . 图片处理
- 为了满足前端显示需要,一个图片在不同的地方需要不同的尺寸,需要剪裁或压缩图片。 
- 原图太大,带宽的资源非常宝贵,为了节省带宽,需要图片压缩。 
- 图片鉴黄 
- 图片加水印 
二 【传统解决方案】
- FastDFS,一个开源的轻量级,需自己部署和维护,解决海量存储问题,但是成本高。 
- GraphicsMagick,号称图像处理领域的瑞士军刀,解决图片处理问题,但是一样成本高。 
三 【七牛云解决方案】
优点:
- 高并发 
- 高可用 
- 易扩展 
- 低成本 
四 【七牛的安全机制】
- 上传凭证:上传文件的时候,需要把uploadToken通过http post传给七牛服务器才能完成身份验证。 
- 管理:如音视频转码,视频加水印,持久化处理等操作时,需要在调用api接口时,在http header 里加入Authorization : QBox AccessToken 
- 下载:如果空间为私有访问时,下载文件需要下载凭证,就是在http get url 后面加入token参数 
五 【注册账号&快速体验】
1 . 快速入门,参考七牛官方文档:
https://developer.qiniu.com/kodo/manual/1233/console-quickstart#step1
注:快速入门 会创建一个存储空间(bucket),后面生成uploadToken需要用到。
2 .生成uploadToken, 因为我们通常是通过api接口上传图片的,根据七牛的安全机制,我们需要先生成uploadToken,然后把uploadToken作为post的参数,保证上传的安全性
uploadToken生成算法
- AccessKey:必须参数,可以在七牛后台生成 
- SecretKey:必须参数,可以在七牛后台生成 
- bocket :必须参数,快速入门里已经创建,名为:test 
- key :可选参数,如果加了该参数,上传文件时,必须和这里的key保持一致 
六 【在Java中实战】
本篇文章采用的是SSM框架结构
1.在pom.xml中引入两个jar包(采用七牛云官方提供的SDK)
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.31</version></dependency><dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><version>7.2.7</version></dependency>
2.创建index.html页面
<html><head><meta charset="UTF-8"><title>Insert title here</title></head><body><form action="/testUpload" method="post" enctype="multipart/form-data"><input type="file" name="file" /><button type="submit">上传</button></form></body></html>
3.创建FileUtil.java(验证图片后缀名)
public class FileUtil {// 图片允许的后缀扩展名public static String[] IMAGE_FILE_EXTD = new String[] { "png", "bmp", "jpg", "jpeg","pdf" };public static boolean isFileAllowed(String fileName) {for (String ext : IMAGE_FILE_EXTD) {if (ext.equals(fileName)) {return true;}}return false;}}
4.创建QiniuService.java
@Servicepublic class QiniuService {private static final Logger logger = LoggerFactory.getLogger(QiniuService.class);// 设置好账号的ACCESS_KEY和SECRET_KEYString ACCESS_KEY = "###################";String SECRET_KEY = "###################";// 要上传的空间String bucketname = "####";// 密钥配置Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);// 构造一个带指定Zone对象的配置类,不同的七云牛存储区域调用不同的zoneConfiguration cfg = new Configuration(Zone.zone0());// ...其他参数参考类注释UploadManager uploadManager = new UploadManager(cfg);// 测试域名,只有30天有效期private static String QINIU_IMAGE_DOMAIN = "http://############/";// 简单上传,使用默认策略,只需要设置上传的空间名就可以了public String getUpToken() {return auth.uploadToken(bucketname);}public String saveImage(MultipartFile file) throws IOException {try {int dotPos = file.getOriginalFilename().lastIndexOf(".");if (dotPos < 0) {return null;}String fileExt = file.getOriginalFilename().substring(dotPos + 1).toLowerCase();// 判断是否是合法的文件后缀if (!FileUtil.isFileAllowed(fileExt)) {return null;}String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileExt;// 调用put方法上传Response res = uploadManager.put(file.getBytes(), fileName, getUpToken());// 打印返回的信息if (res.isOK() && res.isJson()) {// 返回这张存储照片的地址return QINIU_IMAGE_DOMAIN + JSONObject.parseObject(res.bodyString()).get("key");} else {logger.error("七牛异常:" + res.bodyString());return null;}} catch (QiniuException e) {// 请求失败时打印的异常的信息logger.error("七牛异常:" + e.getMessage());return null;}}}
在我们创建存储空间的时候,会选择地区,Zone.zone0()这里代表华东区,如果是华北区则应该写Zone.zone1(),其他地区请查询七牛云文档
5.创建Controller
@Controllerpublic class TestController {@Autowiredprivate QiniuService qiniuService;@RequestMapping(value = "/testUpload", method = RequestMethod.POST)@ResponseBodypublic String uploadImage(@RequestParam("file") MultipartFile file,HttpServletRequest request) {if(file.isEmpty()) {return "error";}try {String fileUrl=qiniuService.saveImage(file);return "success, imageUrl = " + fileUrl;} catch (IOException e) {e.printStackTrace();}return "fail";}}
7.图片处理
url?Imageslim :图片瘦身
url? imageView2/0/w/<Width>/h/<Height> :等比缩放,不裁剪
url? imageView2/1/w/<Width>/h/<Height> :等比缩放,居中裁剪
明明可以靠脸,偏偏要靠技术
与其相忘于江湖,不如扫个二维码
