栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

图片存储及定时清理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

图片存储及定时清理

文章目录
    • 一、 介绍
    • 二、七牛云存储
      • 1、 使用Java SDK操作七牛云 并利用redis定时清理释放磁盘空间
        • 1)需导入如下maven坐标:
        • 2) redis配置文件spring-redis.xml
          • 2.1)在health_backend项目中提供Spring配置文件spring-redis.xml
          • 2.2)将添加的图片名称(已保存到数据库中的)保存到redis的另一个Set集合中
        • 3)在springmvc.xml中配置文件上传组件 + 加载spring-redis.xml配置文件
        • 4)图片上传并预览
          • 4.1)页面:
            • 4.1.1)定义模型数据,用于后面上传文件的图片预览:
            • 4.1.2)定义上传组件:
            • 4.1.3)定义对应的钩子函数:
          • 4.2)后台:
            • 4.2.1)Java SDK操作七牛云封装为工具类
            • 4.2.2)在health_common工程中提供Redis常量类 (common工程的constant包下)
            • 4.2.3) ...Controller:
            • 4.2.4)实现类...ServiceImpl中
        • 5)定时任务 清理垃圾图片
          • 5.1)创建maven工程health_jobs(继承父工程),打包方式为war
          • 5.2)配置:
            • 5.2.1) 配置web.xml (加载spring容器)
            • 5.2.2)配置log4j.properties(resources下)
            • 5.2.3)配置applicationContext-redis.xml(resources下)
            • 5.2.4)配置applicationContext-jobs.xml(resources下)
          • 5.3)创建ClearImgJob定时任务类(health_jobs工程 com.lym.jobs包下)
        • 6)定时清理图片流程总结:
    • 三、定时任务组件Quartz
        • 1 导入maven坐标
        • 2 自定义一个Job
        • 3 提供Spring配置文件spring-jobs.xml(resources包下)
        • 4 编写main方法进行测试
        • 5 cron表达式
          • 5.1) 通过cron表达式可以灵活的定义出符合要求的程序执行的时间
          • 5.2) cron表达式在线生成器

一、 介绍

在实际开发中,我们会有很多处理不同功能的服务器。
分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

如:

  • 应用服务器:负责部署我们的应用
  • 数据库服务器:运行我们的数据库
  • 文件服务器:负责存储用户上传文件的服务器

常见的图片存储方案:

  • 方案一:使用nginx搭建图片服务器
  • 方案二:使用开源的分布式文件存储系统,例如Fastdfs、HDFS等
  • 方案三:使用云存储,例如阿里云、七牛云等
二、七牛云存储

七牛云(隶属于上海七牛信息技术有限公司)是国内领先的以视觉智能和数据智能为核心的企业级云计算服务商,同时也是国内知名智能视频云服务商,累计为 70 多万家企业提供服务,覆盖了国内80%网民。围绕富媒体场景推出了对象存储、融合 CDN 加速、容器云、大数据平台、深度学习平台等产品、并提供一站式智能视频云解决方案。为各行业及应用提供可持续发展的智能视频云生态,帮助企业快速上云,创造更广阔的商业价值。
官网:https://www.qiniu.com/
通过七牛云官网介绍我们可以知道其提供了多种服务,我们主要使用的是七牛云提供的对象存储服务来存储图片。

1、 使用Java SDK操作七牛云 并利用redis定时清理释放磁盘空间

鉴权:
Java SDK的所有的功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的Access Key(相当于用户名)和Secret Key,这对密钥可以在七牛云管理控制台的个人中心(https://portal.qiniu.com/user/key)获得,如下图:

1)需导入如下maven坐标:


  com.qiniu
  qiniu-java-sdk
  7.2.0



  org.quartz-scheduler
  quartz
  2.2.1


  org.quartz-scheduler
  quartz-jobs
  2.2.1

2) redis配置文件spring-redis.xml 2.1)在health_backend项目中提供Spring配置文件spring-redis.xml



	
	
		
			200
		
		
			50
		
		
		
	
	
		
		
		
		
	

2.2)将添加的图片名称(已保存到数据库中的)保存到redis的另一个Set集合中

在health_service_provider项目中提供Spring配置文件spring-redis.xml

内容同(2.1)
3)在springmvc.xml中配置文件上传组件 + 加载spring-redis.xml配置文件

(backend工程中)



  
  
  




Note:health_service_provider项目中的spring-redis.xml不用另写加载了,因为命名为spring…,在health_service_provider的web.xml中 如下代码。所以不用引用了

classpath*:spring*.xml
4)图片上传并预览
  • 流程:
    使用ElementUI提供的el-upload上传组件,将图片先上传到Controller;
    通过Controller调用封装的七牛云工具类,将图片上传到七牛云服务器上(就会有网络地址);
    拿到网络地址,将网络地址值设置给模型数据imageUrl,此时将展示此图片。
4.1)页面: 4.1.1)定义模型数据,用于后面上传文件的图片预览:
imageUrl:null, //模型数据,用于上传图片完成后图片预览
4.1.2)定义上传组件:
  

  
  
  
  

4.1.3)定义对应的钩子函数:
   //文件上传成功后的钩子,response为服务端返回的值,file为当前上传的文件封装成的js对象
handleAvatarSuccess(response, file) {
   	//设置模型数据 展示图片
  		this.imageUrl = "http://pqjroc654.bkt.clouddn.com/"+response.data;
  		this.$message({
    		message: response.message,
    		type: response.flag ? 'success' : 'error'
  		});
  		//设置模型数据(图片名称),后续提交ajax请求时会提交到后台最终保存到数据库
 		 this.formData.img = response.data;
}

//上传文件之前的钩子
beforeAvatarUpload(file) {
  		const isJPG = file.type === 'image/jpeg';//文件类型
  		const isLt2M = file.size / 1024 / 1024 < 2;//文件大小
  		if (!isJPG) {
    		this.$message.error('上传套餐图片只能是 JPG 格式!');
  		}
  		if (!isLt2M) {
    		this.$message.error('上传套餐图片大小不能超过 2MB!');
  		}
  		return isJPG && isLt2M;
}
4.2)后台: 4.2.1)Java SDK操作七牛云封装为工具类
public class QiniuUtils {
    public  static String accessKey = "gf5kMH-bWascazlb4p8QjFjoQCzcEIQNuqle5vCZ";
    public  static String secretKey = "RYawJkLea7dZhVT-30GG3ysY6ytepT-iiJMhdcP7";
    public  static String bucket = "lymhealthproject";//存储空间名称

    public static void upload2Qiniu(String filePath,String fileName){
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone2());
        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
            }
        }
    }

    //上传文件
    public static void upload2Qiniu(byte[] bytes, String fileName){
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone2());
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);

        //默认不指定key的情况下,以文件内容的hash值作为文件名
        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);
            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
            }
        }
    }

    //删除文件
    public static void deleteFileFromQiniu(String fileName){
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone2());
        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());
        }
    }
}
4.2.2)在health_common工程中提供Redis常量类 (common工程的constant包下)
public class RedisConstant {
    //套餐图片所有图片名称
    public static final String SETMEAL_PIC_RESOURCES = "setmealPicResources";
    //套餐图片保存在数据库中的图片名称
    public static final String SETMEAL_PIC_DB_RESOURCES = "setmealPicDbResources";
}
4.2.3) …Controller:
	@Autowired
	private JedisPool jedisPool;//使用JedisPool操作Redis服务
	
	// 图片上传
    @RequestMapping("/upload")
    public Result upload(@RequestParam("imgFile") MultipartFile imgFile){
        try {
            // 1. 生成新fileName:
              // 1)原文件名
            String originalFilename = imgFile.getOriginalFilename();
              // 2)获取问后缀
            int lastIndexOf = originalFilename.lastIndexOf('.');
            String suffix = originalFilename.substring(lastIndexOf);
              // 3)新名字  使用UUID随机产生文件名称,防止同名文件覆盖
            String fileName = UUID.randomUUID().toString()+suffix;
            // 2.上传
            QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName);
			Result result = new Result(true,MessageConstant.PIC_UPLOAD_SUCCESS,fileName);
    		// 3.将上传的图片名称存入Redis,基于Redis的Set集合存储 
    		jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);
    				return result;
        } catch (IOException e) {
            //上传失败
            e.printStackTrace();
            return new Result(false,MessageConstant.PIC_UPLOAD_FAIL);
        }
    }
4.2.4)实现类…ServiceImpl中

(在保存完数据库后将图片名称存储到redis集合中)

	@Autowired
	private JedisPool jedisPool;
	//新增套餐
	public void add(Setmeal setmeal, Integer[] checkgroupIds) {
		// 1 添加套餐
  		setmealDao.add(setmeal);
  		// 2 绑定套餐和检查组的多对多关系
  		if(checkgroupIds != null && checkgroupIds.length > 0){
    		this.setSetmealAndCheckGroup(setmeal.getId(),checkgroupIds);
  		}
  		//3 将图片名称保存到Redis    setmeal.getImg():获得图片名称
  		this.savePic2Redis(setmeal.getImg());
	}
	
	//将图片名称保存到Redis
	private void savePic2Redis(String pic){
  		jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES,pic);
	}
5)定时任务 清理垃圾图片
  • 若不定时清理,则会存在一个问题,就是如果用户只上传了图片而没有最终保存套餐信息到我们的数据库,这时我们上传的图片就变为了垃圾图片。对于这些垃圾图片我们需要定时清理来释放磁盘空间。这就需要我们能够区分出来哪些是垃圾图片,哪些不是垃圾图片。如何实现呢?
  • 计算setmealPicResources集合与setmealPicDbResources集合的差值,结果就是垃圾图片的名称集合,通过定时任务组件Quartz定时清理这些垃圾图片
  • Quartz详情 见三
  • 方案:利用redis来保存图片名称,具体做法为:(详见6))
    (1)当用户上传图片后,将图片名称保存到redis的一个Set集合中; 例如:集合名称为setmealPicResources
    (2)当用户添加套餐后,将图片名称保存到redis的另一个Set集合中;例如:集合名称为setmealPicDbResources
    (3)计算setmealPicResources集合与setmealPicDbResources集合的差值,结果就是垃圾图片的名称集合,清理这些图片即可
5.1)创建maven工程health_jobs(继承父工程),打包方式为war

pom.xml中:依赖…_interface工程;导入Quartz等相关坐标;指定端口;

	
        UTF-8
        1.8
        1.8
    
    
      
        
            com.lym
            health_interface
            1.0-SNAPSHOT
        
      
        
            org.quartz-scheduler
            quartz
        
        
            org.quartz-scheduler
            quartz-jobs
        
    
  
    
        
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                
                    
                    83
                    
                    /
                
            
        
    
5.2)配置: 5.2.1) 配置web.xml (加载spring容器)

  Archetype Created Web Application
  
  
    contextConfigLocation
    classpath*:applicationContext*.xml
  
  
    org.springframework.web.context.ContextLoaderListener
  

5.2.2)配置log4j.properties(resources下)
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=info, stdout
5.2.3)配置applicationContext-redis.xml(resources下)

因为需连接redis数据库,拿到两个集合并计算差值




	
	
		
			200
		
		
			50
		
		
		
	
	
		
		
		
		
	

5.2.4)配置applicationContext-jobs.xml(resources下)

定时任务相关配置



  
	
  
	
  
	
		
		
		
		
	
	
	
		
		
		
		
			
      0/10 * * * * ?
		
	
	
	
		
		
			
				
			
		
	

5.3)创建ClearImgJob定时任务类(health_jobs工程 com.lym.jobs包下)
public class ClearImgJob {
	// applicationContext-jobs.xml中需开启注解   Note:项目中若包含springmvc.xml 其中
        //根据Redis中保存的两个set集合进行差值计算,获得垃圾图片名称集合
        Set set = 
            jedisPool.getResource().sdiff(RedisConstant.SETMEAL_PIC_RESOURCES, 
                                          RedisConstant.SETMEAL_PIC_DB_RESOURCES);
        if(set != null){
            for (String picName : set) {
                //删除七牛云服务器上的图片
                QiniuUtils.deleteFileFromQiniu(picName);
                //从Redis集合中删除图片名称
                jedisPool.getResource().
                    srem(RedisConstant.SETMEAL_PIC_RESOURCES,picName);
            }
        }
    }
}
6)定时清理图片流程总结:

方案:利用redis来保存图片名称,具体做法为:

  • (1)当用户上传图片后,将图片名称保存到redis的一个Set集合中; 例如:集合名称为setmealPicResources
  • (2)当用户添加套餐后,将图片名称保存到redis的另一个Set集合中;例如:集合名称为setmealPicDbResources
  • (3)计算setmealPicResources集合与setmealPicDbResources集合的差值,结果就是垃圾图片的名称集合,清理这些图片即可
    详细:
  • (1)将上传的图片名称保存到redis的Set集合中
    (1.1)在health_backend项目中提供Spring配置文件spring-redis.xml; --> 2.1)
    在springmvc.xml中加载spring-redis.xml配置文件(backend项目中. --> 3)
    (1.2)在health_common工程中提供Redis常量类 (common工程中constant包下)–> 4.2.1)
    (1.3)完善SetmealController,在文件上传成功后将图片名称保存到redis集合中. --> 4.2.2)
  • (2)将添加的图片名称(已保存到数据库中的)保存到redis的另一个Set集合中
    (2.1)在health_service_provider项目中提供Spring配置文件spring-redis.xml. --> 2.2)
    (内容同(1.1))
    (2.2)完善SetmealServiceImpl服务类,在保存完数据库后将图片名称存储到redis集合中 --> 4.2.3)
  • (3)清理垃圾图片
    计算setmealPicResources集合与setmealPicDbResources集合的差值,结果就是垃圾图片的名称,通过定时任务组件Quartz定时清理这些垃圾图片
    (3.1)创建maven工程health_jobs继承父工程,打包方式为war;依赖…_interface工程;导入Quartz等相关坐标;指定端口; -->5.1)
    (3.2)配置(加载spring容器) -->5.2)
    (3.3)创建ClearImgJob定时任务类(health_jobs工程 com.lym.jobs包下) -->5.3)
三、定时任务组件Quartz

Quartz是Job scheduling(作业调度)领域的一个开源项目,Quartz既可以单独使用也可以跟spring框架整合使用,在实际开发中一般会使用后者。使用Quartz可以开发一个或者多个定时任务,每个定时任务可以单独指定执行的时间,例如每隔1小时执行一次、每个月第一天上午10点执行一次、每个月最后一天下午5点执行一次等。
官网:http://www.quartz-scheduler.org/

1 导入maven坐标

  org.quartz-scheduler
  quartz
  2.2.1


  org.quartz-scheduler
  quartz-jobs
  2.2.1

2 自定义一个Job
public class JobDemo {
    public void run(){
        System.out.println("job execute...");
    }
}
3 提供Spring配置文件spring-jobs.xml(resources包下)

​ (1)配置自定义Job (需交给spring工厂初始化);
​ (2)任务描述
​ (3)触发器
​ (4)调度工厂等



	
    
	
    
        
        
        
        
    
    
    
        
        
        
        
            0/10 * * * * ?
        
    
    
    
        
        
            
                
            
        
    

4 编写main方法进行测试

内容:

new ClassPathXmlApplicationContext("spring-jobs.xml");//此时就会自动执行
5 cron表达式 5.1) 通过cron表达式可以灵活的定义出符合要求的程序执行的时间


cron表达式分为七个域,之间使用空格分隔。其中最后一个域(年)可以为空。每个域都有自己允许的值和一些特殊字符构成。使用这些特殊字符可以使我们定义的表达式更加灵活。

下面是对这些特殊字符的介绍:
逗号(,):指定一个值列表,例如使用在月域上1,4,5,7表示1月、4月、5月和7月

横杠(-):指定一个范围,例如在时域上3-6表示3点到6点(即3点、4点、5点、6点)

星号(*):表示这个域上包含所有合法的值。例如,在月份域上使用星号意味着每个月都会触发

斜线(/):表示递增,例如使用在秒域上0/15表示每15秒

问号(?):只能用在日和周域上,但是不能在这两个域上同时使用。表示不指定

井号(#):只能使用在周域上,用于指定月份中的第几周的哪一天,例如6#3,意思是某月的第三个周五 (6=星期五,3意味着月份中的第三周)

L:某域上允许的最后一个值。只能使用在日和周域上。当用在日域上,表示的是在月域上指定的月份的最后一天。用于周域上时,表示周的最后一天,就是星期六

W:W 字符代表着工作日 (星期一到星期五),只能用在日域上,它用来指定离指定日的最近的一个工作日

5.2) cron表达式在线生成器

根据需求生成表达式:http://cron.qqe2.com/

  1. 编写main方法进行测试
    内容:
new ClassPathXmlApplicationContext("spring-jobs.xml");//此时就会自动执行
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1020142.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号