热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:图片存储方案七牛云存储

本文由编程笔记#小编为大家整理,主要介绍了图片存储方案-七牛云存储相关的知识,希望对你有一定的参考价值。
本文由编程笔记#小编为大家整理,主要介绍了图片存储方案-七牛云存储相关的知识,希望对你有一定的参考价值。






简介


在我们实际的项目中,经常会将服务器进行划分,比如:专门运行我们程序的应用服务器、专门运行我们数据库的数据库服务器、还有负责文件存储的文件服务器、负责视频存储的服务器。


这些服务器组成我们的所有服务、各司其职,这样划分的目的相比大家也知道,减轻一台服务器服务器的压力。


当用户请求我们应用应用服务器的时候,由我们的应用再分别访问我们数据库服务器、文件存储服务器等,最后将请求的资源返回给我们的用户,这样构成整个应用的请求过程:



图片存储方案-七牛云存储

我们今天要讲的就是图片存储,图片储存的方案有很多,比如:可以使用Fastdfs或者HDFS、使用nginx搭建图片存储服务器。


现在比较流行的就是「云存储」,使用「阿里云、七牛云」等。这一节我们使用七牛云做了实例讲解。


七牛云入门


图片存储方案-七牛云存储注册完后直接登陆,登陆后右上角有一个「管理控制平台」,点击管理控制平台的产品首页,还要进行「实名认证才能创建对象存储存储空间」,实名认证后点击对象存储的「立即添加」:


图片存储方案-七牛云存储点击立即添加后来到对象存储空间的创建页面,点击「新建空间」图片存储方案-七牛云存储


创建存储空间后可以看见自己创建的空间的详细信息,并且可以创建多个存储空间,每一个存储空间相互独立,不会互相干扰。


七牛云提供了多种的方式操作对象存储服务,我们这里使用的是Java SDK方式,具体的使用可以在开发者中心查看:



图片存储方案-七牛云存储


图片存储方案-七牛云存储

Java SDK开发文档里面有详细的操作的API说明,以及要引入的依赖坐标。



图片存储方案-七牛云存储

代码实战


首先在自己的项目中引入七牛云的依赖坐标:



  com.qiniu
  qiniu-java-sdk
  7.2.0


从Java SDK的操作文档中,简单操作文档的上传的示例代码如下:


//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region0());
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传,填写AK和SK以及buket name
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
//文件路径,如果是Windows情况下,格式是 D:\qiniu\test.png
String localFilePath = "/home/qiniu/test.png";
//默认不指定key的情况下,以文件内容的hash值作为文件名
String key = null;
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
    Response response = uploadManager.put(localFilePath, key, upToken);
    //解析上传成功的结果
    DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
    System.out.println(putRet.key);
    System.out.println(putRet.hash);
} catch (QiniuException ex) {
    Response r = ex.response;
    System.err.println(r.toString());
    try {
        System.err.println(r.bodyString());
    } catch (QiniuException ex2) {
        //ignore
    }
}

上面的是根据文件路径来上传文件,还支持字节数组上传到空间中:


//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region0());
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
//默认不指定key的情况下,以文件内容的hash值作为文件名
String key = null;
try {
    byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
    Auth auth = Auth.create(accessKey, secretKey);
    String upToken = auth.uploadToken(bucket);
    try {
        Response response = uploadManager.put(uploadBytes, key, upToken);
        //解析上传成功的结果
        DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        System.out.println(putRet.key);
        System.out.println(putRet.hash);
    } catch (QiniuException ex) {
        Response r = ex.response;
        System.err.println(r.toString());
        try {
            System.err.println(r.bodyString());
        } catch (QiniuException ex2) {
            //ignore
        }
    }
} catch (UnsupportedEncodingException ex) {
    //ignore
}

以及删除上传的文件:


//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region0());
//...其他参数参考类注释
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
String key = "your file key";
Auth auth = Auth.create(accessKey, secretKey);
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
    bucketManager.delete(bucket, key);
} catch (QiniuException ex) {
    //如果遇到异常,说明删除失败
    System.err.println(ex.code());
    System.err.println(ex.response.toString());
}

上面有提到比较关键的信息,因为使用七牛云服务要进行认证,上面有三个数据「AK、SK和bucket name」,AK和SK也就是AccessKey/SecretKey


AK和SK这个信息中可以在如下的页面获取,bucket name也就是你在创建存储空间的时候填信息的名称:




有了这些信息,我们可以将上面的代码封装成自己的工具类:


public class QiniuUtils {
    // 填写你的accessKey值
    public  static String accessKey = "your accessKey";
     // 填写你的secretKey 值
    public  static String secretKey = "your secretKey ";
    // 填写你的 bucket name值
    public  static String bucket = "your bucket name";
    /**
     * 上传文件
     * @param filePath 文件路径
     * @param fileName 文件名
     */
    public static void uploadFile(String filePath,String fileName){
        Configuration cfg = new Configuration(Zone.zone0());
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(filePath, fileName, upToken);
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException ex) {
            Response r = ex.response;
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
    }
    /**
     * 上传文件
     * @param bytes 文件字节数组
     * @param fileName 文件名
     */
    public static void uploadFile(byte[] bytes, String fileName){
        Configuration cfg = new Configuration(Zone.zone0());
        UploadManager uploadManager = new UploadManager(cfg);
        String key = fileName;
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(bytes, key, upToken);
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException ex) {
            Response r = ex.response;
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
    }
    /**
     * 删除文件
     * @param fileName 文件名
     */
    public static void deleteFile(String fileName){
        Configuration cfg = new Configuration(Zone.zone0());
        String key = fileName;
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            bucketManager.delete(bucket, key);
        } catch (QiniuException ex) {
            System.err.println(ex.code());
            System.err.println(ex.response.toString());
        }
    }
}

然后写一个接口作为文件上传的测试类:


@Autowired 
private JedisPool jedisPool; //图片上传 
@RequestMapping("/uploadImage"
public ResponseResult upload(@RequestParam("imgFile")MultipartFile imgFile){ 
 try{
     //获取原始文件名 
  String originalFilename = imgFile.getOriginalFilename(); 
  //获取图片名后缀 
  int lastIndexOf = originalFilename.lastIndexOf("."); 
  String suffix = originalFilename.substring(lastIndexOf ‐ 1); 
  //使用UUID生成图片名,防止名称一样
  String fileName = UUID.randomUUID().toString() + suffix; QiniuUtils.uploadFile(imgFile.getBytes(),fileName); //图片上传成功 
  ResponseResult result = new ResponseResult (ResponseConstant.UPLOAD_SUCCESS,"上传成功"); 
  result.setData(fileName); 
  //将上传图片名称存入Redis,基于Redis的Set集合存储 
  jedisPool.getResource().sadd(ImageConstant.ALl_PIC_RESOURCES,fileName ); 
  return result; 
 }catch (Exception e){ 
  e.printStackTrace(); //图片上传失败 
  return new ResponseResult (ResponseConstant.UPLOAD_FAIL,"文件上传失败"); 
 } 
}

这里在作为图片上传的时候使用Redis的set集合进行缓存,这样做的目的就是,用户自己点击上传文件后,填写完信息,但是后面就有可能包填写的消息取消掉。


这样这些图片就会成为我们的垃圾图片,若是没有存储这些图片的信息,从此也找不到这些图片,这样这些垃圾图片就会占用空间。


我们的解决方案就是,先把所有的这些图片还存在Redis的一个Set集合中,叫做ALl_PIC_RESOURCES


然后把上传成功的图片还存在Redis的另一个Set集合中叫做L:SUCCESS_PIC_RESOURCES


最后系统起一个定时任务,定期清理掉ALl_PIC_RESOURCESL:SUCCESS_PIC_RESOURCES差值的图片数据,清理时间可以设置在晚上凌晨,这样对系统的性能影响就不会那么大。


定时任务可以选用Quartz,我相信这个定时任务框架应该很多人都用过,在项目中直接引入依赖坐标:



     org.quartz-scheduler
     quartz
 

 
     org.quartz-scheduler
     quartz-jobs
 


具体的定时任务的配置可以自行百度一下,这里只给出,定时任务清理图片的方法:


public void deleteImage(){
        //比较两个Set集合得到差集,得到无效的图片名称集合
        Set imageSet = redisTemplate.opsForSet().difference("ALl_PIC_RESOURCES""L:SUCCESS_PIC_RESOURCES");
        for (String imageName : imageSet ) {
            //删除图片
            QiniuUtils.deleteFileFrom(imageName );
            //删除缓存中无用的图片
            redisTemplate.boundSetOps("ALl_PIC_RESOURCES").remove(imageName );
        }
    }

好了,今天的实例讲解就到这里了,觉得有帮助的求个三连,我们下期再见。






推荐阅读
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • 深入理解:AJAX学习指南
    本文详细探讨了AJAX的基本概念、工作原理及其在现代Web开发中的应用,旨在为初学者提供全面的学习资料。 ... [详细]
  • 大数据领域的职业路径与角色解析
    本文将深入探讨大数据领域的各种职业和工作角色,帮助读者全面了解大数据行业的需求、市场趋势,以及从入门到高级专业人士的职业发展路径。文章还将详细介绍不同公司对大数据人才的需求,并解析各岗位的具体职责、所需技能和经验。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 从0到1搭建大数据平台
    从0到1搭建大数据平台 ... [详细]
  • 【漫画解析】数据已删,存储空间为何未减?揭秘背后真相
    在数据迁移过程中,即使删除了原有数据,存储空间却未必会相应减少。本文通过漫画形式解析了这一现象背后的真相。具体来说,使用 `mysqldump` 命令进行数据导出时,该工具作为 MySQL 的逻辑备份工具,通过连接数据库并查询所需数据,将其转换为 SQL 语句。然而,这种操作并不会立即释放存储空间,因为数据库系统可能保留了已删除数据的碎片信息。文章进一步探讨了如何优化存储管理,以确保数据删除后能够有效回收存储空间。 ... [详细]
  • 软件测试行业深度解析:迈向高薪的必经之路
    本文深入探讨了软件测试行业的发展现状及未来趋势,旨在帮助有志于在该领域取得高薪的技术人员明确职业方向和发展路径。 ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
  • Windows操作系统提供了Encrypting File System (EFS)作为内置的数据加密工具,特别适用于对NTFS分区上的文件和文件夹进行加密处理。本文将详细介绍如何使用EFS加密文件夹,以及加密过程中的注意事项。 ... [详细]
  • 回顾两年前春节期间的一个个人项目,该项目原本计划参加竞赛,但最终作为练习项目完成。独自完成了从编码到UI设计的全部工作,尽管代码量不大,但仍有一定的参考价值。本文将详细介绍该项目的背景、功能及技术实现。 ... [详细]
  • 如何在PHP中安装Xdebug扩展
    本文介绍了如何从PECL下载并编译安装Xdebug扩展,以及如何配置PHP和PHPStorm以启用调试功能。 ... [详细]
  • 本文详细介绍了如何搭建一个高可用的MongoDB集群,包括环境准备、用户配置、目录创建、MongoDB安装、配置文件设置、集群组件部署等步骤。特别关注分片、读写分离及负载均衡的实现。 ... [详细]
author-avatar
牛牛的牛66_674
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有