精华内容
下载资源
问答
  • 本地 redis .rdb 文件上传到 阿里云 redis: 为这个问题,纠结了好久。之前还搜索了好多文章,还看的 唯品会的 redis 迁移工具。 其实阿里云文档,这些都有,我们需要耐下心来,好好研究,之前就是太浮躁了,瞎看...
    本地 redis .rdb 文件上传到 阿里云 redis:
    	为这个问题,纠结了好久。之前还搜索了好多文章,还看的 唯品会的 redis 迁移工具。
    	其实阿里云文档,这些都有,我们需要耐下心来,好好研究,之前就是太浮躁了,瞎看,一看有点复杂,就不想看。
    
    参考文档:
    	云数据库 Redis 版
    		1.公网链接 - https://help.aliyun.com/document_detail/43850.html
    			注意:我们从本地 PC 访问 阿里云的 Redis 数据库,默认是拒绝的,需要一些配置。需要仔细了解 『前提条件』。
    
    			前提条件:
    			『
    				若 Redis 实例属于专有网络(VPC),ECS 必须与 Redis 实例属于同一个 VPC。
    				若 Redis 实例属于经典网络,ECS 必须与 Redis 实例属于同一节点(地域)。
    				若 Redis 实例开启了 IP 白名单,必须将 ECS 的内网地址加入白名单列表内。
    			』
    			我们项目的 Redis 实例,是属于 "经典网络",在其他地域的 ESC 上尝试了半天,确实访问不了。
    
    			Redis 实例,只支持 ECS 访问,要想在公网上访问,文档也给出了途径:
    				『可以通过在 ECS 上配置端口映射或者端口转发实现』
    
    			好像是需要安装一个 rinetd 服务。
    
    		2.使用 redis-port 恢复数据 - https://help.aliyun.com/document_detail/90931.html
    			这篇文档,讲述的有2点:
    				1>从阿里云 redis 上,下载备份文件(阿里云redis,会根据我们的设置自动备份,我们就是下载这些已备份的文件)
    				2>将本地的 redis 文件,恢复到 阿里云redis
    					这个是我们需要的功能,但是并没有在这个文档提到,参考下面链接:
    						https://help.aliyun.com/document_detail/66012.html
    
    			1>下载 redis 备份
    				1)安装 openAPI
    					pip install aliyun-python-sdk-core #安装阿里云OpenAPI依赖包
    
    					// 这个需要安装 pip,自行搜索
    
    				2)下载工具包
    					wget http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/73964/cn_zh/1536832169445/redis-rdb-auto-restore.zip
    
    				3)解压zip包,编辑 config.json 配置文件,配置我们的 阿里云的 AccesskeyID, AccesskeySecret,regionid。
    					unzip redis-rdb-auto-restore.zip
    					vim config.json
    						{
    							AccesskeyID: 'xxx',
    							AccesskeySecret: 'xxx',
    							regionid: 'cn-beijing',
    						}
    
    				4)执行脚本
    					python rdb_restore.py -c xxx -t xxx -p 6379 -a xxx -d 2018-09-20
    
    					注意:
    						如果一天之内有多个备份文件的话,务必加上 -b 参数,如需传入多个备份id请用逗号隔开,如:xxx,xxx,xxx
    
    				5)参数说明:
    					-c - 云数据库 redis 实例ID(--inistance_id)
    					-t - 云数据库 redis 域名(--target)
    					-p - 云数据库 redis 端口(--port)
    					-a - 云数据库 redis 密码(--auth)
    					-d - 备份的日期(--day)
    					-o - 备份到本地的路径以及文件名,默认路径是 '/root/'(--output)
    					-b - 具体的实例备份id,选填,对于一天有多个备份的时候选择具体备份,如果需要传入多个备份的话请用逗号隔开,如:xxx,xxxx,xxxx(--backup)
    					更多命令参考:python rdb_restore.py -h
    
    
    			2>上传本地 .rdb 文件到阿里云 redis 
    				1)下载 redis-port
    					wget http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/66008/cn_zh/1526545851725/redis-port
    
    					注意:
    						如果已经使用了 '第一步' 里,下载了备份工具包,里面已经有了 'redis-port' 了,我们就不用再次下载了
    
    
    				2)./redis-port restore --input=/xxx/xxx.rdb --target=xxx:6379 --auth=xxx
    
    					注意:
    						1.确保 redis-port 有执行权限。如果没有,执行:chmod o+x redis-port
    						2.非常关键!!!
    							测试了下 redis-port,并不会删除目前阿里云 redis 中的数据,会将我们本地的 .rdb 文件里的数据新增到里面去,所以我们需要根据自己的需求来操作。
    							如果完全使用本地的,阿里云redis不使用,直接点击 阿里云redis里的『清除数据』。
    
    				3)参数说明:
    					--input - 本地我们的 rdb 文件
    					--target - 云数据库 redis 域名:云数据库 redis 端口
    					--auth - 云数据库 redis 密码
    					--filterkey - 过滤指定的key。"str1|str2|str3":过滤包含 str1 或 str2 或 str3 的键。
    					--targetdb - 将要同步入云数据库 redis 的 DB
    					--rewrite - 覆盖已经写入的key
    					--bigkeysize - 当写入的 value 大于 SIZE 时,走大 key 写入模式
    					更多命令参考:./redis-port -h
    
    	安装 pip
    		参照官方安装:
    			https://pip.pypa.io/en/stable/installing/
    
    其他参考文章:
    	https://www.cnblogs.com/weifeng1463/p/9052045.html

     

    展开全文
  • 将图片存储在了七牛云服务器中。但是这个过程存在一个问题,就是如 果用户只上传了图片而没有最终保存套餐信息到我们的数据库,这时我们上传的图片...1、当用户上传图片后,将图片名称保存到redis的一个Set集合中,...

    将图片存储在了七牛云服务器中。但是这个过程存在一个问题,就是如 果用户只上传了图片而没有最终保存套餐信息到我们的数据库,这时我们上传的图片就变为了垃圾图 片。对于这些垃圾图片我们需要定时清理来释放磁盘空间。这就需要我们能够区分出来哪些是垃圾图 片,哪些不是垃圾图片。如何实现呢?

    方案就是利用redis来保存图片名称,具体做法为:
    1、当用户上传图片后,将图片名称保存到redis的一个Set集合中,例如集合名称为 setmealPicResources
    2、当用户添加套餐后,将图片名称保存到redis的另一个Set集合中,例如集合名称为 setmealPicDbResources
    3、计算setmealPicResources集合与setmealPicDbResources集合的差值,结果就是垃圾图片的名称 集合,清理这些图片即可

    实现步骤:
    (1)在health_backend项目中提供Spring配置文件spring-redis.xml 并在spring-mvc中导入

    在这里插入图片描述
    在这里插入图片描述

    (2)在health_common工程中提供Redis常量类

    在这里插入图片描述

    (3)完善SetmealController,在文件上传成功后将图片名称保存到redis集合中

    在这里插入图片描述

    (4)在health_service_provider项目中提供Spring配置文件applicationContext-redis.xml()

    在这里插入图片描述

    (5)完善SetmealServiceImpl服务类,在保存完成套餐信息后将图片名称存储到redis集合中

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • docker使用redis.conf配置文件方式启动redis无反应无日志  如题,场景重现:因为配置多了,不想通过... 上传到/mydata/redis/data目录后,因为我是在普通用户下,所以需要将redis.conf文件修改下属主和组: ..

    转载自:https://www.cnblogs.com/wuxun1997/p/11804089.html

    docker使用redis.conf配置文件方式启动redis无反应无日志

      如题,场景重现:因为配置多了,不想通过参数来启动docker容器中的redis,特意上github找了对应版本的redis.conf,修改了相关配置,只让本机使用:

     

     

      上传到/mydata/redis/data目录后,因为我是在普通用户下,所以需要将redis.conf文件修改下属主和组:

    复制代码

    [mall@VM_0_7_centos data]$ ll
    total 48
    -rw-r--r-- 1 polkitd input     0 Nov  6 03:02 appendonly.aof
    -rw-r--r-- 1 root    root  47759 Nov  6 10:49 redis.conf
    [mall@VM_0_7_centos data]$ sudo chown polkitd.input redis.conf 
    [mall@VM_0_7_centos data]$ ll
    total 48
    -rw-r--r-- 1 polkitd input     0 Nov  6 03:02 appendonly.aof
    -rw-r--r-- 1 polkitd input 47759 Nov  6 10:49 redis.conf

    复制代码

     

      接着停掉原来的redis、删除原有docker容器中的redis镜像,再重新以配置文件方式启动:

    复制代码

    [mall@VM_0_7_centos data]$ sudo docker stop redis
    redis
    [mall@VM_0_7_centos data]$ sudo docker rm redis
    redis
    [mall@VM_0_7_centos data]$ sudo docker run -p 6379:6379 --name redis -v /mydata/redis/data/redis.conf:/etc/redis/redis.conf -v /mydata/redis/data:/data -d redis:3.2 redis-server /etc/redis/redis.conf
    a02b1a8d290e276d401a612f9a8239a01aab3b2feb952dfed50b33da2d3f5a54

    复制代码

      

      然而,没有反应,进程并未成功起来:

     

       也没有报错日志:

     

      解决方案:在redis.conf中注掉daemonize yes这一行,或者改为daemonize no。因为我们的docker run里参数-d就是以守护进程方式启动redis,而配置文件里daemonize yes这个东东再次以守护进程方式启动,而且它会读取pidfile这个配置的文件作为进程ID文件。说白了,就是docker启动参数跟redis.conf配置冲突了。

      改redis.conf:

     

       再启docker,ok了:

     

      现在没法从外网连接进来了:

    展开全文
  • 文件上传

    2020-10-12 19:33:25
    文件上传到redis服务器,断点续传 1.文件上传的到redis里的流程图 2.基本流程 将一个视频,分为大小为4M大小的视频块,将视频块上传到到队列服务器,此次上传的视频块是没有任何排序的,然后将队列中的视频块放到redis...

    将文件上传到redis服务器,断点续传

    1.文件上传的到redis里的流程图在这里插入图片描述
    2.基本流程
    将一个视频,分为大小为4M大小的视频块,将视频块上传到到队列服务器,此次上传的视频块是没有任何排序的,然后将队列中的视频块放到redis服务器中,redis服务器用来排序,在传送到redis中可以不用考虑了丢东西,redis排序完后再传送给队列服务器,此次队列服务器中的视频块是完整的,中间会进行视频的校验,校验的依据就是md5的值,如果md5的值和之前是相等的,说明视频没有丢字节,说明视频是完整的,然后存储到i指定路径中
    1.创建视频:2.传入视频元数据3.循环上传视频

    /**
    	 package cn.tedu.controller;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.Serializable;
    import java.util.List;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    
    import cn.tedu.entity.Course;
    import cn.tedu.entity.User;
    import cn.tedu.entity.Video;
    import cn.tedu.util.UUIDUtil;
    import cn.tedu.util.UploadFileUtil;
    import cn.tedu.util.UrlUtil;
    import cn.tedu.vo.ReceiveInfo;
    import cn.tedu.vo.UploadInfo;
    import cn.tedu.vo.VideoBlockMessage;
    
    @Controller
    @RequestMapping("/video")
    public class UploadController {
    	
    	@Autowired
    	private UrlUtil urlUtil;
    	
    	@Resource(name="amqpTemplate")
    	private AmqpTemplate amqpTemplate;
    	@Resource(name="redisTemplate")
    	private RedisTemplate<Serializable,Serializable> redisTemplate;
    	
    	
    	/**
    	 * 1.创建视频
    	 * @param userId    用户的id    uuid
    	 * @param format    默认是json
    	 * @param request   
    	 * @param response
    	 * @return   UploadInfo对象
    	 */
    	@RequestMapping(value="/create",method=RequestMethod.POST)
    	@ResponseBody
    	public UploadInfo videoCreate(
    			String userId,
    			String format,
    			HttpServletRequest request,
    			HttpServletResponse response) {
    		System.out.println(userId+"   "+format);
    		UploadInfo uploadInfo=new  UploadInfo();
    		//开始创建视频
    		if(userId==null || "".equals(userId) || userId.length()!=36) {
    			uploadInfo.setMsgerror("用户不合法");
    			return uploadInfo;
    		}
    		//能执行到此处说明用户的id是合法的
    		uploadInfo.setUserId(userId);
    		uploadInfo.setVideoId(UUIDUtil.getUUID());
    		uploadInfo.setMetaurl(this.urlUtil.getMetaurl());
    		uploadInfo.setChunkurl(this.urlUtil.getChunkurl());
    		uploadInfo.setMsgerror(null);
    		return uploadInfo;
    	}
    	
    	//2.上传视频的元数据,即视频的基本信息
    	@RequestMapping(value="/uploadmeta",method=RequestMethod.POST)
    	@ResponseBody
    	public ReceiveInfo videoUploadMeta(
    			HttpServletRequest request,
    			HttpServletResponse response,
    			String userId,
    			String videoId,
    			String videoTitle,
    			String videoTag,
    			String videoDescription,
    			String videoFileName,
    			String videoFileSize,
    			String courseId,
    			String md5,
    			String format,
    			String first,
    			MultipartFile addPicture) {
    		ReceiveInfo receiveInfo=new ReceiveInfo();
    		String originalFileName=null;
    		try {
    			String realPath=request.getServletContext().getRealPath("/videoimage");
    			File realFile=new File(realPath);
    			if(!realFile.exists()) {
    				realFile.mkdir();
    			}
    			if(addPicture==null || addPicture.isEmpty()) {
    				receiveInfo.setResult(-1);
    				receiveInfo.setMsg("error");
    				return receiveInfo;
    			}else {
    				//至少上传的视频封面截图是存在
    				originalFileName=addPicture.getOriginalFilename();
    				boolean flag=UploadFileUtil.uploadImage(addPicture,videoId,true,64,realPath);
    				if(!flag) {
    					//说明封面截图图片存储失败
    					receiveInfo.setResult(-1);
    					receiveInfo.setMsg("error");
    					return receiveInfo;
    				}
    			}
    			//能执行到此处,说明,封面截图图片上传成功了
    			//准备把视频的元数据存储到队列中
    			Video video=new Video();
    			video.setId(videoId);
    			video.setUser(new User());
    			video.getUser().setId(userId);
    			video.setTitle(videoTitle);
    			video.setTag(videoTag);
    			video.setIntroduction(videoDescription);
    			video.setFileName(videoId+videoFileName.substring(videoFileName.lastIndexOf(".")));
    			video.setFileSize(Long.parseLong(videoFileSize));
    			video.setCourse(new Course());
    			video.getCourse().setId(courseId);
    			video.setMd5(md5);
    			video.setFirst(first);
    			String extName=originalFileName.substring(originalFileName.lastIndexOf(".")+1);
    			video.setPicture(videoId+"."+extName);
    			if("1".equals(first)) {
    				//说明是第一次上传
    				//构建head对象,存储到队列中,即把video中的元数据存储到队列中
    				this.amqpTemplate.convertAndSend("videoCacheQueue",video);
    			}else if("2".equals(first)) {
    				//说明非第一次上传,断点续传
    				//从redis中获取最后上传的完的那块的信息
    				//这个块有可能是head(video),也有可能是videoBlockMessage
    				List<Serializable> currentVideoAllBlock=this.redisTemplate.boundListOps(videoId).range(0,-1);
    				if (currentVideoAllBlock.size()==1) {
    					//说明redis中只有视频的头
    					receiveInfo.setBlockIndex(0);
    					receiveInfo.setBlockNumber(UploadFileUtil.findBlockNumber(Long.parseLong(videoFileSize)));
    					
    				}else if (currentVideoAllBlock.size()>1) {
    					//说明至少有一个文件块上传成功
    					//从list集合中获取最后一个块,且必须是VideoBlockMessage类型
    					VideoBlockMessage vbm=(VideoBlockMessage) currentVideoAllBlock.get(currentVideoAllBlock.size()-1);
    					receiveInfo.setBlockIndex(vbm.getBlockIndex());
    					receiveInfo.setBlockNumber(UploadFileUtil.findBlockNumber(Long.parseLong(videoFileSize)));
    				}
    			}
    			//能执行到此处,说明可能是first==1时候成功
    			//也有可能是first==2的时候成功
    			receiveInfo.setResult(0);
    			receiveInfo.setMsg("success");
    			
    			
    		}catch(Exception e) {
    			//一定是有异常了
    			receiveInfo.setResult(-1);
    			receiveInfo.setMsg("error");
    			e.printStackTrace();
    		}
    		
    		
    		
    		
    		return receiveInfo;
    	}
    	//3.循环上传视频的文件块
    	@RequestMapping(value="/chunk",method=RequestMethod.POST)
    	@ResponseBody
    	public ReceiveInfo VideoChunk(
    			String userId,
    			String videoId,
    			String blockNumber,
    			String blockIndex,
    			String format,
    			MultipartFile file) {
    		ReceiveInfo receiveInfo=new ReceiveInfo();
    		
    		try {
    			//构建VideoBlockMessage对象
    			VideoBlockMessage videoBlockMessage=new VideoBlockMessage();
    			videoBlockMessage.setUserId(userId);
    			videoBlockMessage.setVideoId(videoId);
    			videoBlockMessage.setBlockIndex(Integer.parseInt(blockIndex));
    			videoBlockMessage.setBlockNumber(Integer.parseInt(blockNumber));
    			byte[] data=file.getBytes();
    			videoBlockMessage.setData(data);
    			videoBlockMessage.setLength(data.length);
    			
    			//把VideoBlockMessage对象发送队列videoCacheQueue中
    			this.amqpTemplate.convertAndSend("videoCacheQueue",videoBlockMessage);
    			
    			receiveInfo.setResult(0);
    			receiveInfo.setMsg("success");
    			receiveInfo.setBlockIndex(Integer.parseInt(blockIndex));
    			receiveInfo.setBlockNumber(Integer.parseInt(blockNumber));
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			receiveInfo.setResult(-1);
    			receiveInfo.setMsg("error");
    			receiveInfo.setBlockIndex(Integer.parseInt(blockIndex));
    			receiveInfo.setBlockNumber(Integer.parseInt(blockNumber));
    			e.printStackTrace();
    		}
    		return receiveInfo;
    		
    	}	
    }
    
    
    将视频分块:下面代码是将视频分块
    
    //将视频分块的代码
    package cn.tedu.util;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.RandomAccessFile;
    
    import org.apache.http.entity.mime.content.AbstractContentBody;
    
    public class BlockStreamBody extends AbstractContentBody{
        //文件块的大小
    	private long blockSize=0;
    	//上传的文件的名称
        private String fileName;
        
        //以下三个重要的数据,是给重要的方法writeTo
        //重要:文件的总块数
        private int blockNumber;
        //重要:文件的块的索引
        private int blockIndex;
        //重要:要对此文件进行分割
    	private File targetFile;
    	
    	
    	public BlockStreamBody(int blockNumber,int blockIndex,File targetFile) {
    		super("application/octet-stream");
    		this.blockNumber=blockNumber;
    		this.blockIndex=blockIndex;
    		this.targetFile=targetFile;
    		
    		this.fileName=this.targetFile.getName();
    		if(blockIndex<blockNumber) {
    			this.blockSize=GlobalConstant.BLOCK_SIZE;
    		}else {
    			this.blockSize=targetFile.length()-GlobalConstant.BLOCK_SIZE*(blockNumber-1);
    		}		
    	}
    
    	@Override
    	public String getFilename() {
    		// TODO Auto-generated method stub
    		return this.fileName;
    	}
    
    	/**
    	 * 此方法每调用一次,只输出文件中的某一个块的数据
    	 */
    	@Override
    	public void writeTo(OutputStream out) throws IOException {
    		byte[] b=new byte[1024];
    		RandomAccessFile raf=new RandomAccessFile(this.targetFile,"r");
    		if(this.blockIndex==1) {
    			//处理第一块
    			int n=0;
    			long readLength=0;//存储的是读取的字节数
    			while(readLength<=this.blockSize-1024) {
    				n=raf.read(b,0,1024);
    				readLength+=1024;
    				out.write(b,0,n);
    			}
    			if(readLength<this.blockSize) {
    				//余下的不足1024个字节在此读取
    				n=raf.read(b,0,(int)(blockSize-readLength));
    				out.write(b,0,n);
    			}
    		}else if(blockIndex<blockNumber) {
    			//处理的不是第一块,也不是最后一块
    			//需要给文件的指针定位
    			raf.seek(GlobalConstant.BLOCK_SIZE*(blockIndex-1));
    			int n=0;
    			long readLength=0;//存储的是读取的字节数
    			while(readLength<=this.blockSize-1024) {
    				n=raf.read(b,0,1024);
    				readLength+=1024;
    				out.write(b,0,n);
    			}
    			if(readLength<this.blockSize) {
    				//余下的不足1024个字节在此读取
    				n=raf.read(b,0,(int)(blockSize-readLength));
    				out.write(b,0,n);
    			}			
    		}else {
    			//处理的是最后一块
    			raf.seek(GlobalConstant.BLOCK_SIZE*(blockIndex-1));
    			int n=0;
    			while((n=raf.read(b,0,1024))!=-1) {
    				out.write(b,0,n);
    			}
    		}
    		raf.close();	
    	}
    
    	@Override
    	public String getTransferEncoding() {
    		// TODO Auto-generated method stub
    		return "binary";
    	}
    
    	@Override
    	public long getContentLength() {
    		// TODO Auto-generated method stub
    		return this.blockSize;
    	}
    	
    }
    
    
    	什么是md5值:就相当于一个安全校验码,在视频上传一开始的时候会生成一个md5码,如果这个视频在上传的过程中发生了改变,md5的值就会跟着改变.
    	下面的代码是三种生成md5值的方法
    
    package cn.tedu.util;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.math.BigInteger;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.security.MessageDigest;
    
    import org.apache.commons.codec.digest.DigestUtils;
    import org.apache.commons.io.IOUtils;
    
    /**
     * 生成md5的工具
     * 可以生成某个字符串的md5
     * 可以生成某个文件的md5
     * @author Administrator
     *
     */
    public class MD5Util {
    	/**
    	 * jdk方式
    	 * 生成某个文件的md5值
    	 * @param file   指定某个文件
    	 * @return  文件的md5值
    	 * @throws Exception
    	 */
    	public static String getMd5(File file)throws Exception{
    		String md5String=null;
    		FileInputStream fis=new FileInputStream(file);
    		MappedByteBuffer byteBuffer=fis.getChannel().map(FileChannel.MapMode.READ_ONLY,0,file.length());
    		MessageDigest md5=MessageDigest.getInstance("MD5");
    		md5.update(byteBuffer);
    		BigInteger bi=new BigInteger(1,md5.digest());
    		md5String=bi.toString(16);
    		fis.close();
    		return md5String;
    	}
    	/**
    	 * apache 的commons codec 组件
    	 * 生成某个文件的md5值
    	 * @param path   指定某个文件的路径
    	 * @return   文件的md5值
    	 * @throws Exception
    	 */
    	public static String getMd5(String path)throws Exception{
    		String md5String=null;
    		FileInputStream fis=new FileInputStream(path);
    		md5String=DigestUtils.md5Hex(IOUtils.toByteArray(fis));
    		IOUtils.closeQuietly(fis);
    		return md5String;
    	}
    	/**
    	 * 生成某个字符串的md5值
    	 * @param str   源字符串
    	 * @param salt  盐
    	 * @return  字符串的md5
    	 * @throws Exception
    	 */
    	public static String getMd5(String str,String salt)throws Exception{
    		String md5String=null;
    		MessageDigest md5=MessageDigest.getInstance("MD5");
    		md5.update(str.getBytes());;
    		md5.update(salt.getBytes());
    		byte[] digest=md5.digest();
    		md5String=org.apache.commons.codec.binary.Hex.encodeHexString(digest);
    		return md5String;
    	}
    	public static void main(String[] args) {
    		try {
    			System.out.println(MD5Util.getMd5(new  File("d:/ks.mp4")));
    			System.out.println(MD5Util.getMd5("d:/ks.mp4"));
    			System.out.println(MD5Util.getMd5("123","admin"));
    		}catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    

    3.将队列服务器中的视频头和视频块传送到redis服务器中VideoCache类

    package cn.tedu.mq.listen;
    
    import java.io.Serializable;
    import java.security.MessageDigest;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    import javax.annotation.Resource;
    
    import org.apache.commons.codec.binary.Hex;
    import org.springframework.data.redis.core.RedisTemplate;
    
    
    import cn.tedu.entity.Video;
    import cn.tedu.service.VideoService;
    import cn.tedu.util.AssembledFileUtil;
    import cn.tedu.util.GlobalConstant;
    import cn.tedu.vo.VideoBlockMessage;
    
    public class VideoCache {
    	@Resource(name = "videoService")
    	private VideoService videoService;
    	@Resource(name="redisTemplate")
    	private RedisTemplate<Serializable,Serializable> redisTemplate;
    	public void videoCacheListen(Object obj) {
    		System.out.println("VideoCache.videoCacheListen()-->"+obj.getClass());
    		try {
    			if(obj.getClass()==Video.class) {
    				//说明处理视频缓存队列中的视频head   Video类型
    				System.out.println("拿到了Video对象");
    			    //把拿到的Video的对昂临时存储在redis中
    				Video video=(Video)obj;
    				this.redisTemplate.boundListOps(video.getId()).rightPush(video);
    				//在redis服务器中对videoState状态置为正在上传
    				this.redisTemplate.boundHashOps("videoState").put(video.getId(),GlobalConstant.UPLOADING);
    				//定时清除redis中的指定的数据
    				this.redisTemplate.expire(video.getId(),1,TimeUnit.DAYS);
    				this.redisTemplate.boundHashOps("videoState").expire(7,TimeUnit.DAYS);
    			}else if(obj.getClass()==VideoBlockMessage.class) {
    				//说明处理的是队列中的VideoBlockMessage对象
    				System.out.println("拿到了VideoBlockMessage对象");
    				//将视频块从队列服务器取出
    				VideoBlockMessage videoBlockMessage=(VideoBlockMessage)obj;
    				
    				//只要任何一个环节上传失败,则忽略队列中的后面的所以的视频块
    				//此处可能出现的问题,就是数据存储失败,和md5不相等
    				//此处从redis中获取videoState中的某一个视频id对应的状态
    				String state=(String)this.redisTemplate.boundHashOps("videoState").get(videoBlockMessage.getVideoId());
    				if (state.equals(GlobalConstant.UPLOAD_FAILURE)) {
    					return;
    				}
    				//不是failure,即上传成功,把视频块对象存储给rides
    				this.redisTemplate.boundListOps(videoBlockMessage.getVideoId()).rightPush(videoBlockMessage);
    				//无论上传视频头还是视频块的对象存储给redis,都说明是正在上传给rides
    				this.redisTemplate.boundHashOps("videoState").put(videoBlockMessage.getVideoId(),GlobalConstant.UPLOADING);
    				//判断blockIndex是否等于bilockNumber
    				if (videoBlockMessage.getBlockIndex()==videoBlockMessage.getBlockNumber()) {
    					//说明是最后一块了,视频文件数据宽已经全部存储redis中
    					
    					//从rides中取出视频id对应所以视频头和视频块的数据
    					List<Serializable> currentVideoAllBlock=this.redisTemplate.boundListOps(videoBlockMessage.getVideoId()).range(0, -1);
    					//取出视频头
    					Video metaData=(Video)currentVideoAllBlock.get(0);
    					//获取med5的消息摘要
    					MessageDigest md5_messageDigest=MessageDigest.getInstance("MD5");
    					//取出后面的对象都是videoBlockMessage类型对象
    					for (int i = 1; i <currentVideoAllBlock.size(); i++) {
    						//每循环一次取出的是一个视频块的对象
    						VideoBlockMessage vbm=(VideoBlockMessage)currentVideoAllBlock.get(i);
    						md5_messageDigest.update(vbm.getData());
    					}
    					byte[] digest=md5_messageDigest.digest();
    					String newMd5=Hex.encodeHexString(digest);
    					//判断取出的视频文件的md5值和原始的视频文件md5的值是否相等
    					if (metaData.getMd5().equals(newMd5)) {
    						System.out.println("文件是完整的");
    						//如果文件是完整的要更新数据库,要把数据插入t_video表
    						boolean flag=this.videoService.save(metaData);
    						if (flag) {
    							System.out.println("视频信息存储到数据库T_video表成功");
    							metaData.setState(Integer.parseInt((GlobalConstant.UPLOAD_OVER)));
    							//给redis的视频状态设置成uploader
    							this.redisTemplate.boundHashOps("videoState").put(videoBlockMessage.getVideoId(),GlobalConstant.UPLOAD_OVER);
    							//说明视频文件全部上传成功,且md5也相等,可以合并文件块,
    							//合并完成后的视频给内网使用
    							AssembledFileUtil.assembledFile(currentVideoAllBlock);
    							
    						}else {
    							System.out.println("视频信息存储数据库失败");
    							//给rides中的视频状态设置为failure
    							this.redisTemplate.boundHashOps("videoState").put(videoBlockMessage.getVideoId(),GlobalConstant.UPLOAD_FAILURE);
    						}
    					}else {
    						System.out.println("md5不相等");
    						//设置视频上传失败
    						this.redisTemplate.boundHashOps("videoState").put(videoBlockMessage.getVideoId(),GlobalConstant.UPLOAD_FAILURE);
    						return;
    					}
    				}
    			}
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} 
    		
    	}
    	
    }
    
    

    创建service接口用于编写存储视频的方法

    package cn.tedu.service;
    
    import cn.tedu.entity.Video;
    import cn.tedu.vo.Page;
    import cn.tedu.vo.Result;
    
    public interface VideoService {
    	/**
    	 * 存储视频信息的业务方法
    	 * @param metaData 视频对象
    	 * @return true视频存储成功
    	 * 			false:视频存储失败
    	 */
    	public boolean save(Video metaData);
    
    }
    

    定义一个serviceimpl类实现service接口,用来实现save方法来给数据库添加数据

    //此处的@Transactional必须写因为对数据库的数据进行了改变
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    	@Override
    	public boolean save(Video metaData) {
    		boolean flag=false;
    		this.videoMapper.save(metaData);
    		flag=true;
    		return flag;
    	}
    

    定义VidoeMapper接口

    package cn.tedu.dao;
    
    import java.util.List;
    
    import cn.tedu.entity.Video;
    import cn.tedu.vo.Page;
    
    public interface VideoMapper {
    	/**
    	 * geit_video表添加视频数据
    	 * @param metaData
    	 */
    	public void save(Video metaData);
    
    }
    
    

    创建一个VideoMapperImpl类用来实现VideoMapper接口的save方法此方法用来执行数据库

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="cn.tedu.dao.VideoMapper">
    
        <!-- role的ResultMap -->
    	<resultMap type="Role" id="roleMap">
    	    <!-- 注意:从表中的外键id,不能跟主表的主键id名字相同 -->
    		<id property="id" column="role_id" />
    		<result property="name" column="role_name"/>
    	</resultMap>
    	<!-- user的resultMap -->
    	<resultMap type="User" id="userMap">
    		<id property="id" column="user_id" jdbcType="VARCHAR"/>
    		<result property="loginName" column="user_loginname" jdbcType="VARCHAR"/>
    		<result property="loginType" column="user_logintype" jdbcType="VARCHAR"/>
    		<result property="nickName" column="user_nickname" jdbcType="VARCHAR"/>
    		<result property="password" column="user_password" jdbcType="VARCHAR"/>
    		<result property="type" column="user_type" jdbcType="INTEGER"/>
    		<result property="head" column="user_head" jdbcType="VARCHAR"/>
    		<result property="score" column="user_score" jdbcType="INTEGER"/>
    		<result property="isLock" column="user_islock" jdbcType="CHAR"/>
    		<result property="pwdState" column="user_pwdstate" jdbcType="VARCHAR"/>
    		<result property="regDate" column="user_regdate" jdbcType="TIMESTAMP"/>
    		<result property="age" column="user_age" jdbcType="INTEGER"/>
    		<result property="sex" column="user_sex" jdbcType="CHAR"/>
    		<result property="introduction" column="user_introduction" jdbcType="VARCHAR"/>
    		<collection property="roles" ofType="Role" 
    		            javaType="java.util.List"
    		            resultMap="roleMap"></collection>
    	</resultMap>
    	
    	<!-- Course的resultMap -->
    	<resultMap type="Course" id="courseMap">
    		<id property="id" column="course_id"/>
    		<result property="name" column="course_name"/>
    		<result property="picture" column="course_picture"/>
    		<result property="order" column="course_order" jdbcType="INTEGER"/>
    		<result property="desc" column="course_desc"/>
    	</resultMap>
    	
    	
    	<resultMap type="Video" id="videoMap">
    		<id property="id" column="video_id" jdbcType="CHAR"/>
    		<result property="title" column="video_title" jdbcType="VARCHAR"/>
    		<result property="special" column="video_special" jdbcType="INTEGER"/>
    		<result property="forsale" column="video_forsale" jdbcType="CHAR"/>
    		<result property="count" column="video_click_count" jdbcType="BIGINT"/>
    		<result property="introduction" column="video_introduction" jdbcType="VARCHAR"/>
    		<result property="picture" column="video_picture" jdbcType="VARCHAR"/>
    		<result property="picturecc" column="video_picture_cc" jdbcType="VARCHAR"/>
    		<result property="fileName" column="video_filename" jdbcType="VARCHAR"/>
    		<result property="videoUrlcc" column="video_url_cc" jdbcType="VARCHAR"/>
    		<result property="state" column="video_state" jdbcType="INTEGER"/>
    		<result property="ontime" column="video_ontime" jdbcType="TIMESTAMP"/>
    		<result property="difficulty" column="video_difficulty" jdbcType="INTEGER"/>
    		<result property="md5" column="md5" jdbcType="VARCHAR"/>
    		<result property="tag" column="video_tag" jdbcType="VARCHAR"/>
    		<result property="fileSize" column="video_filesize" jdbcType="BIGINT"/>
    		<result property="metaurl" column="metaurl" jdbcType="VARCHAR"/>
    		<result property="chunkurl" column="chunkurl" jdbcType="VARCHAR"/>
    		<result property="ccvid" column="ccvid" jdbcType="VARCHAR"/>
    		<association property="user" column="user_id"
    		             javaType="User" resultMap="userMap">		
    		</association>
    		<association property="course" column="course_id"
    		             javaType="Course" resultMap="courseMap">
    		
    		</association>
    	</resultMap>
    	<!-- 插入视频数据 -->
    	<insert id="save"
    	        parameterType="Video">
    	   insert into t_video
    	    (
    	      video_id,
    	      video_title,
    	      video_tag,
    	      course_id,
    	      user_id,
    	      video_introduction,
    	      video_filename,
    	      video_filesize,
    	      video_picture,
    	      video_state,
    	      md5
    	    )
    	      values
    	      (
    	       #{id},
    	       #{title},
    	       #{tag},
    	       #{course.id},
    	       #{user.id},
    	       #{introduction},
    	       #{fileName},
    	       #{fileSize,jdbcType=BIGINT},
    	       #{picture},
    	       #{state},
    	       #{md5}
    	      )
    	</insert>
    </mapper>
    

    将视频合并

    package cn.tedu.util;
    
    import java.io.File;
    import java.io.RandomAccessFile;
    import java.io.Serializable;
    import java.util.List;
    
    import cn.tedu.entity.Video;
    import cn.tedu.vo.VideoBlockMessage;
    
    /**
     * 专门用来合并文件的工具类
     * @author Mechrev
     * d:/upload/userId/videoid/videoid.mp4
     */
    
    public class AssembledFileUtil {
    	
    	public static void assembledFile(List<Serializable> currentVideoAllBlock) {
    		String userId="";
    		String videoId="";
    		int blockNumber=0;
    		int blockIndex=0;
    		try {
    			if (currentVideoAllBlock!=null&&currentVideoAllBlock.size()>0) {
    				Video video=(Video)currentVideoAllBlock.get(0);
    				userId=video.getUser().getId();
    				videoId=video.getId();
    				//构建文件存储路径d:/upload/userId/videoId/
    				String uploadedURL=GlobalConstant.UPLOAD_ABSTRACT_PATH
    						+File.separator+userId+File.separator+videoId+File.separator;
    				File realPath=new File(uploadedURL);
    				if (!realPath.exists()) {
    					realPath.mkdirs();
    					
    				}
    				//文件的真实名字
    				String fileName=video.getFileName();
    				//截取拓展名字
    				String extName=fileName.substring(fileName.lastIndexOf(".")+1);
    				//准备开始合并文件,拼装路径
    				RandomAccessFile fileWrite=new RandomAccessFile(uploadedURL+videoId+"."+extName,"rw");
    				//将视频块存储到byte集合中
    				for (int i = 1; i < currentVideoAllBlock.size(); i++) {
    					VideoBlockMessage vbm=(VideoBlockMessage)currentVideoAllBlock.get(i);
    					if (vbm!=null) {
    						byte[] block=vbm.getData();
    						int read=block.length;
    						long offset=(i-1)*GlobalConstant.BLOCK_SIZE;
    						fileWrite.seek(offset);
    						//写入文件
    						fileWrite.write(block,0,read);
    					}
    				}
    				fileWrite.close();
    			}
    		} catch (Exception e) {
    			// TODO: handle exception
    			e.printStackTrace();
    		}
    		
    	}
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    }
    
    

    4.测试类

    package cn.tedu.test;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.mime.HttpMultipartMode;
    import org.apache.http.entity.mime.MultipartEntityBuilder;
    import org.apache.http.entity.mime.content.ContentBody;
    import org.apache.http.entity.mime.content.FileBody;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.protocol.HTTP;
    import org.apache.http.util.CharsetUtils;
    import org.apache.http.util.EntityUtils;
    
    import com.alibaba.fastjson.JSON;
    
    import cn.tedu.util.BlockStreamBody;
    import cn.tedu.util.MD5Util;
    import cn.tedu.util.UploadFileUtil;
    
    public class TestUploadController {
    	/**
    	 * 此方法是一个私有的方法,用来给MultipartEntityBuilder存储数据的
    	 * 注意,数据仅限文本
    	 * @param params  要提交的数据 
    	 * @param multipartEntityBuilder  把提交的数据存储到此对象中
    	 */
    	private void buildMultipartEntity(Map<String, String> params, MultipartEntityBuilder multipartEntityBuilder) {
    
    		//解决中文乱码问题
    		ContentType contentType=ContentType.create(HTTP.PLAIN_TEXT_TYPE,HTTP.UTF_8);
    		
    		//把map集合中的key转换成list集合
    		List<String> keys=new ArrayList<String>(params.keySet());
    		//把list集合中的所有的key排序,不区分大小的排序
    		Collections.sort(keys,String.CASE_INSENSITIVE_ORDER);
    		for(Iterator<String> iterator=keys.iterator();iterator.hasNext();) {
    			String key=iterator.next();
    			String value=params.get(key);
    			if(StringUtils.isNoneBlank(value)) {
    				multipartEntityBuilder.addTextBody(key, value, contentType);
    			}
    		}
    	}
    	
    	
    	
    	//1.创建视频的方法
    	public Map<String,String> videoCreate(
    			Map<String,String> params,
    			String serverUrlCreate){
    		Map<String,String> returnMap=null;
    		String content=null;
    		try {
    			//用HttpClent模拟http请求,相当于用浏览器模拟发送请求,接收返回数据
    			HttpClient httpClient=HttpClients.createDefault();
    			HttpPost httpPost=new HttpPost(serverUrlCreate);
    			
    			//给post方式添加提交的数据
    			MultipartEntityBuilder multipartEntityBuilder=MultipartEntityBuilder.create();
    			multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    			
    			this.buildMultipartEntity(params,multipartEntityBuilder);
    			
    			httpPost.setEntity(multipartEntityBuilder.build());
    						
    			//发送一个post请求,返回的记过是HttpResponse对象
    			HttpResponse response=httpClient.execute(httpPost);
    			//从response对象中解析出来返回的结果数据
    			//状态码就是象 200 404 500之类的
    			int status=response.getStatusLine().getStatusCode();
    			if(status==HttpStatus.SC_OK) {
    				//sc_ok值是200,说明响应成功,则获取响应的实体内容
    				HttpEntity entity=response.getEntity();
    				content=EntityUtils.toString(entity);
    				//关闭httpClient连接
    				httpClient.getConnectionManager().shutdown();
    			}
    			//输出响应的结果数据
    			//System.out.println("content="+content);
    			if(content!=null) {
    				returnMap=(Map<String,String>)JSON.parse(content.trim());
    				//System.out.println("contentMap="+contentMap);
    			}
    		}catch(Exception e) {
    			e.printStackTrace();
    		}		
    		return returnMap;
    	}
    	
    	/**
    	 * 2.上传视频元数据的方法
    	 * @param metaParams    传递给服务器的参数数据,即视频文件的信息
    	 * @param videoPicture  视频的封面截图
    	 * @param serverUrl     上传视频元数据的服务器地址
    	 * @return  返回的结果是map集合
    	 *          result    0:成功   -1失败
    	 *          msg       返回消息提示
    	 *          blockNumber   视频文件的总块数
    	 *          blockIndex    最后上传成功的那个快的索引
    	 */
    	public Map<String, Object> uploadMetaData(Map<String, String> metaParams, File videoPicture, String serverUrl) {
    		Map<String,Object> returnMetaMap=null;
    		String content=null;
    		try {
    			//用HttpClent模拟http请求,相当于用浏览器模拟发送请求,接收返回数据
    			HttpClient httpClient=HttpClients.createDefault();
    			HttpPost httpPost=new HttpPost(serverUrl);
    			
    			//给post方式添加提交的数据
    			MultipartEntityBuilder multipartEntityBuilder=MultipartEntityBuilder.create();
    			multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    			
    			//添加文本,把metaParams中的文本数据,存储给multipartEntityBuilder对象
    			this.buildMultipartEntity(metaParams,multipartEntityBuilder);
    			
    			//添加文件
    			ContentBody contentBody=new FileBody(videoPicture);
    			multipartEntityBuilder.addPart("addPicture",contentBody);
    			
    			httpPost.setEntity(multipartEntityBuilder.build());
    						
    			//发送一个post请求,返回的记过是HttpResponse对象
    			HttpResponse response=httpClient.execute(httpPost);
    			//从response对象中解析出来返回的结果数据
    			//状态码就是象 200 404 500之类的
    			int status=response.getStatusLine().getStatusCode();
    			if(status==HttpStatus.SC_OK) {
    				//sc_ok值是200,说明响应成功,则获取响应的实体内容
    				HttpEntity entity=response.getEntity();
    				content=EntityUtils.toString(entity);
    				//关闭httpClient连接
    				httpClient.getConnectionManager().shutdown();
    			}
    			//输出响应的结果数据
    			//System.out.println("content="+content);
    			if(content!=null) {
    				returnMetaMap=(Map<String,Object>)JSON.parse(content.trim());
    				//System.out.println("contentMap="+contentMap);
    			}
    		}catch(Exception e) {
    			e.printStackTrace();
    		}		
    		return returnMetaMap;
    	}
    	
    	//
    	/**
    	 * 3.上传文件块的方法 
    	 * @param chunkParams 服务器需要的参数
    	 * @param filePath  文件的实际路径,
    	 * @param serverUrl  服务器url地址
    	 * @return  返回的结果
    	 *         result
    	 *         msg
    	 *         blockNumber
    	 *         blockIndex
    	 */
    	private Map<String, String> uploadChunkToServer(
    			Map<String, String> chunkParams,
    			String filePath,
    			String serverUrl) {
    		Map<String,String> returnMap=null;
    		String content=null;
    		try {
    			//用HttpClent模拟http请求,相当于用浏览器模拟发送请求,接收返回数据
    			HttpClient httpClient=HttpClients.createDefault();
    			HttpPost httpPost=new HttpPost(serverUrl);
    			
    			//给post方式添加提交的数据
    			MultipartEntityBuilder multipartEntityBuilder=MultipartEntityBuilder.create();
    			multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    			
    			//添加文本,把metaParams中的文本数据,存储给multipartEntityBuilder对象
    			this.buildMultipartEntity(chunkParams,multipartEntityBuilder);
    			
    			//添加文件块,指的是文件中的某一个块
    			int blockNumber=Integer.parseInt(chunkParams.get("blockNumber"));
    			int blockIndex=Integer.parseInt(chunkParams.get("blockIndex"));
    			
    			//构建文件块(4M)
    			ContentBody contentBody=new BlockStreamBody(blockNumber,blockIndex,new File(filePath));
    			multipartEntityBuilder.addPart("file",contentBody);
    			multipartEntityBuilder.setCharset(CharsetUtils.get("UTF-8"));
    			
    			
    			httpPost.setEntity(multipartEntityBuilder.build());
    						
    			//发送一个post请求,返回的记过是HttpResponse对象
    			HttpResponse response=httpClient.execute(httpPost);
    			//从response对象中解析出来返回的结果数据
    			//状态码就是象 200 404 500之类的
    			int status=response.getStatusLine().getStatusCode();
    			if(status==HttpStatus.SC_OK) {
    				//sc_ok值是200,说明响应成功,则获取响应的实体内容
    				HttpEntity entity=response.getEntity();
    				content=EntityUtils.toString(entity);
    				//关闭httpClient连接
    				httpClient.getConnectionManager().shutdown();
    			}
    			//输出响应的结果数据
    			//System.out.println("content="+content);
    			if(content!=null) {
    				return returnMap=(Map<String,String>)JSON.parse(content.trim());
    				//System.out.println("contentMap="+contentMap);
    			}
    		}catch(Exception e) {
    			e.printStackTrace();
    		}
    		
    		return returnMap;
    	}
    	
    	
    	
    
    	public static void main(String[] args) {
    		try {
    			//emulator:模拟器   模拟上传所有上传视频的所有过程
    			TestUploadController emulator=new TestUploadController();
    			//0.准备一些必要的数据
    			String filePath="d:/ks.mp4";
    			String fileName="ks.mp4";
    			long fileSize=0;
    			File targetFile=new File(filePath);
    			if(targetFile.exists()) {
    				fileSize=targetFile.length();
    				//1.调用创建视频的方法
    				//给创建视频准备一些必要的数据
    				String serverUrlCreate="http://localhost:8080/tes_server/video/create";
    				Map<String,String> params=new HashMap<String,String>();
    				params.put("userId", "7008ffa6-e01d-48ed-a460-dbf2a4908bfa");
    				params.put("format", "json");
    				//调用创建视频的方法
    				Map<String,String> createMap=emulator.videoCreate(params, serverUrlCreate);
    				System.out.println("createMap-->"+createMap);
    				String msgerror=createMap.get("msgerror");
    				
    				if(msgerror==null) {
    					//没有错误信息,说明创建视频是成功的
    					//2.调用上传视频的元数据,即视频文件的基本信息
    					//准备视频文件的一些基本信息
    					Map<String,String> metaParams=new HashMap<String,String>(createMap);
    					String serverUrl=metaParams.get("metaurl");
    					
    					metaParams.put("videoTitle", "快闪视频");
    					metaParams.put("videoTag", "java娱乐");
    					metaParams.put("videoDescription", "很好玩的视频");
    					metaParams.put("videoFileName", fileName);
    					metaParams.put("videoFileSize", fileSize+"");
    					metaParams.put("courseId", "8c2ded0e-0455-4631-a3c4-b3c50aeda12f");
    					metaParams.put("md5", MD5Util.getMd5(targetFile));
    					metaParams.put("format", "json");
    					metaParams.put("first", "1");
    					metaParams.remove("metaurl");
    					metaParams.remove("chunkurl");
    					metaParams.remove("msgerror");
    					File videoPicture=new File("d:/video.png");//视频的封面
    					
    					Map<String,Object> returnMetaMap=emulator.uploadMetaData(metaParams,videoPicture,serverUrl);
    					System.out.println("returnMetaMap-->"+returnMetaMap);
    					//3.调用上传视频的文件块
    					//上传视频文件之前,要先把视频文件分块
    					String msg=returnMetaMap.get("msg").toString();
    					if("success".equals(msg)) {
    						//说明元数据上传成功
    						//准备一些数据
    						//blockIndex代表的是最后一个正确上传的文件块的索引
    						//blockNumber代表文件分块的总数
    						//这两个值是从上传元数据成功后的map集合获取的
    						int blockIndex=(Integer)returnMetaMap.get("blockIndex")+1;
    						int blockNumber=(Integer)returnMetaMap.get("blockNumber");
    						if(blockNumber==0) {
    							//说明first==1的情况
    							blockNumber=UploadFileUtil.findBlockNumber(fileSize);
    						}
    						Map<String,String> chunkParams=new HashMap<String,String>();
    						chunkParams.put("userId", "7008ffa6-e01d-48ed-a460-dbf2a4908bfa");
    						chunkParams.put("videoId", createMap.get("videoId"));
    						chunkParams.put("blockNumber", blockNumber+"");
    						chunkParams.put("format", "json");
    						
    						serverUrl=createMap.get("chunkurl");
    						//上传视频块
    						for(int i=blockIndex;i<=blockNumber;i++) {
    							chunkParams.put("blockIndex", i+"");
    							Map<String,String> returnChunkMap=emulator.uploadChunkToServer(chunkParams,filePath,serverUrl);
    							System.out.println("returnChunkMap-->"+returnChunkMap);
    							if("error".equals(returnChunkMap.get("msg"))) {
    								//说明上传的某个文件块失败,不在继续上传后续的文件块了
    								break;
    							}
    						}
    						
    						
    						
    						
    						
    						
    						
    						
    						
    						
    					}
    				}
    				
    				
    				
    			}			
    		}catch(Exception e) {
    			e.printStackTrace();
    		}finally {
    			
    		}
    		
    	}
    }
    
    
    展开全文
  • 首先我的lua脚本文件放在了目录下:/home/younger/lua/countwords.lua 进入你的redis安装目录下面的src文件夹下,比如我的安装目录在/home/younger/soft/redis-5.0.5/src 输入如下命令 ./redis-cli -h localhost -p ...
  • redis

    2019-09-16 16:55:30
    redis编译与安装 1. 解压redisredis源代码文件上传到Linux系统之中,随后将其解压到home/jiangbang/redis/src/ 目录中 tar xzvf /home/jiangbang/redis-3.2.5.tar.gz -C /home/jiangbang/...
  • Redis安装Linux

    2018-12-05 11:04:33
    1.将Redis压缩包上传到Linux 使用rz命令,上传文件需要安装文件上传工具, 上传之后解压文件 2.安装gcc编译软件 使用命令yum install gcc 如果不是纯净版镜像则不需要下载 3.安装Redis 进入redis解压后的目录实行命令...
  • redis安装配置文件配置

    万次阅读 2018-04-04 09:22:34
    环境:  虚拟机redhat5.5安装redis4.0.2  虚拟机IP:192.168.60.130  reids端口:6379 安装步骤不详述了(可参考: 亲密...2.xftp上传到redhat5.5并解压 3.编译安装redis 4.将解压后的redis4.0.2中的redis.conf
  • 目前项目中需要存储一些文件、视频等。于是乎,查找了一些关于文件服务器资料。其中有Lustre、HDFS、Gluster、Alluxio、Ceph 、FastDFS。下面简单介绍一下: Lustre 是一个大规模的、安全可靠的、具备高可用性的集群...
  • 安装Redis

    2018-11-29 14:23:00
    1 解压Redis 创建一个redis的文件夹,用户存放redis文件 mkdir /usr/local/redis ...通过ftp工具把下载好的redis安装包上传到redis文件夹下。 解压: cd /usr/local/redis tar -vxzf redis-3.2.10.tar.gz...
  • 此片文章是将 .Net Core 发布 Docker 上,并且连接在 Docker上的 Redis上传文件到本机文件夹和连接 sqlserver 数据库的续篇。打包镜像之后我们发布的目标位置下,打开 PowerShell 执行如下打包代码等待 ...
  • 最早想用tomcat8的版本...1、将tomcat-redis-session-1.0-SNAPSHOT.jar、jedis-2.7.2.jar、commons-pool2-2.0.jar上传到 tomcat/lib 2,修改文件tomcat/conf/context.xml,添加如下内容。 1 2 3 4...
  • 第一步:redis的源码包上传到linux系统。 第二步:解压缩redis。tar zxvf redis-3.0.0.tar.gz 第三步:编译。cd redis-3.0.0 进入redis源码目录。make 第四步:修改redis.conf文件 注释掉这个 修改守护进程,改为...
  • 定时刷新,一但那边的服务器上传文件,就下载 2.从Redis中获取文件名称(此时的Redis相当于一个消息队列) /** * @Author Ragty * @Description 定时程序(每十秒请求一次) * @Date 15:05 2019/3/19 **/ ...
  • 解压缩下载好的Redis安装文件,选择合适的安装目录进行安装; 第三步、运行CMD在redis所在目录启动,运行命令:redis-server redis.windows.conf: 第四步、避免关闭窗口不可访问,添加Redis服务windows服务中: ...
  • CentOs安装redis

    2017-11-22 12:17:41
    下载最新版本的redis (https://redis.io/download) 通过xft将文件上传到服务器上 tar xzf redis-4.0.2.tar.gz 解压文件 跳转到redis-4.0.2中执行make指令 跳转到redis-4.0.2/src中运行./redis-server开启redis服务
  • 使用FileZilla将redis源码上传到linux中 解压源码 编译redis 安装redis 将源码中redis的配置文件拷贝到安装目录下 启动redis 修改配置文件,将redis启动方式修改为后端启动 ...
  • redis 安装

    2017-08-25 18:51:44
    阿里云 6379 hly123  说明:目前用于缓存,之后可能用于session共享。 redis安装 (安装文件同级目录redis-3.2.10.tar....1)上传redis安装文件redis-3.2.10.tar.gz)阿里云usr/local 2)cd usr/local,解压re
  • OSS 官方给出的 java SDK 是这样的,上传文件的时候使用监听器来监听上传的进度,以实现上传进度,官方示例如下: public class PutObjectProgressListener implements ProgressListener { private long ...
  • redis安装

    2019-10-02 20:45:18
    步骤:1、 将Windows下下载的压缩文件上传到Linux下。我们可以通过filezilla等FTP软件上传,这里通过secureCRT进行上传。步骤如下:? alt + p? put c:/redis-2.6.16.tar.gz? 完成上传2、 解压文件? tar –zxvf redis...
  • redisCluster搭建

    2020-08-03 11:14:47
    redis文件上传两种方式 将文件下载本地,通过本地进行上传 文件下载地址 http://download.redis.io/releases/redis-5.0.8.tar.gz 文件上传 rz 直接将文件下载Linux系统中 (wegt -p 预存文件地址 文件路径...
  • Redis安装

    2020-10-13 14:20:38
    Redis安装Redis安装编译–>测试–>安装修改redis.conf配置文件开启6379的端口号 Redis安装 第一步预安装gcc和make 安装gcc yum install -y gcc make 检查有无gcc ...使用rz命令上传刚刚下载的redis
  • redis搭建 和 redis集群搭建

    热门讨论 2019-03-22 09:59:07
    2.使用xftp将redis的tar包上传到虚拟机中,在这里我新建了一个software文件夹用来存放上传的文件。 切换到根目录里 mkdir software 3.解压缩redis的tar包 tar zxf redis-3.0.0.tar.gz 4.切换到解压缩的redis目录里面...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 866
精华内容 346
关键字:

文件上传到redis

redis 订阅