本次讲解springboot使用(NOSQL)mongodb数据库作为文件存储服务器,在自己练习的是项目里,一直在想着用数据库来存储文件,公司项目是建立一个ftp服务器,我觉得这样延展性不好,如果多台服务器,就会产生文件丢失的问题,直到后来发现了mongodb,看到的一瞬间,眼前一亮,这就是为了存储文件二诞生的呀,果断就学习了一下mongodb,并用springboot集成了mongodb,作为业务上的文件存储服务器,并且这样的好处就是关联性比较强,MySQL与mongodb建立起关联关系,同事mongodb支持分布式,为以后的维护以及拓展留下了良好的基石。

MongoDB

MongoDB是一种非关系型数据库(NoSql),很好的实现了面向对象的思想(OO思想),在Mongo DB中 每一条记录都是一个Document对象。Mongo DB最大的优势在于所有的数据持久操作都无需开发人员手动编写SQL语句,直接调用方法就可以轻松的实现CRUD操作。

MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是可以应用于各种规模的企业、各个行业以及各类应用程序的开源数据库。作为一个适用于敏捷开发的数据库,MongoDB的数据模式可以随着应用程序的发展而灵活地更新。与此同时,它也为开发人员 提供了传统数据库的功能:二级索引,完整的查询系统以及严格一致性等等。 MongoDB能够使企业更加具有敏捷性和可扩展性,各种规模的企业都可以通过使用MongoDB来创建新的应用,提高与客户之间的工作效率,加快产品上市时间,以及降低企业成本。

MongoDB是专为可扩展性,高性能和高可用性而设计的数据库。它可以从单服务器部署扩展到大型、复杂的多数据中心架构。利用内存计算的优势,MongoDB能够提供高性能的数据读写操作。 MongoDB的本地复制和自动故障转移功能使您的应用程序具有企业级的可靠性和操作灵活性。

安装MongoDB

安装环境:centos7

安装文档参考:centos7 yum安装mongodb

具体的我就不写安装操作,网上百度一下,也可参照链接上的操作

springboot集成mongodb

pom.xml

<!-- mongodb文件存储 -->
        <dependency> 
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-starter-data-mongodb</artifactId>
	    </dependency>

这里面有一点小区别,mongodb中的大小限制, 即单个文档大小不能超过16M。如果使用大文件存储就很难用springboot支持的mongodb,遇此情况可以采用GridFS存储大数据量信息

application.properties

##################################################
# 上传文件大小限制
##################################################
spring.servlet.multipart.max-file-size=16MB
spring.servlet.multipart.max-request-size=16MB
##################################################
# MongoDB数据库连接配置
##################################################
spring.data.mongodb.uri=mongodb://118.25.95.95:27017/inventory
#spring.data.mongodb.uri=mongodb://192.168.31.131:27017/inventory

本次讲解的是springboot支持的mongodb服务

/**
 * 
 * MONGODB文件读写操作对象
 * @author zhouxinlei
 *
 */
@Document
public class MongoDBFile implements java.io.Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	@Id  // 主键
    private String id;
    private String name; // 文件名称
    private String contentType; // 文件类型
    private long size;
    private Date uploadDate;
    private String md5;
    private byte[] content; // 文件内容
    private String path; // 文件路径
	
    public MongoDBFile() {
		super();
		// TODO Auto-generated constructor stub
	}
    
    public MongoDBFile(String name, String contentType, long size,byte[] content) {
        this.name = name;
        this.contentType = contentType;
        this.size = size;
        this.uploadDate = new Date();
        this.content = content;
    }

	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getContentType() {
		return contentType;
	}
	public void setContentType(String contentType) {
		this.contentType = contentType;
	}
	public long getSize() {
		return size;
	}
	public void setSize(long size) {
		this.size = size;
	}
	public Date getUploadDate() {
		return uploadDate;
	}
	public void setUploadDate(Date uploadDate) {
		this.uploadDate = uploadDate;
	}
	public String getMd5() {
		return md5;
	}
	public void setMd5(String md5) {
		this.md5 = md5;
	}
	public byte[] getContent() {
		return content;
	}
	public void setContent(byte[] content) {
		this.content = content;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	@Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (object == null || getClass() != object.getClass()) {
            return false;
        }
        MongoDBFile fileInfo = (MongoDBFile) object;
        return java.util.Objects.equals(size, fileInfo.size)
                && java.util.Objects.equals(name, fileInfo.name)
                && java.util.Objects.equals(contentType, fileInfo.contentType)
                && java.util.Objects.equals(uploadDate, fileInfo.uploadDate)
                && java.util.Objects.equals(md5, fileInfo.md5)
                && java.util.Objects.equals(id, fileInfo.id);
    }

    @Override
    public int hashCode() {
        return java.util.Objects.hash(name, contentType, size, uploadDate, md5, id);
    }

	@Override
	public String toString() {
		return "MongoDBFile [id=" + id + ", name=" + name + ", contentType=" + contentType + ", size=" + size
				+ ", uploadDate=" + uploadDate + ", md5=" + md5 + ", content=" + Arrays.toString(content) + ", path="
				+ path + "]";
	}

}

文档类是类似与 JPA 中的实体的概念。主要采用的是 Spring Data MongoDB 中的注解,用于标识这是个 NoSQL 中的文档概念。

其次还需要一个将文档信息存储内容与业务字段具体关联起来,我采用加了一张表

@Entity
@Table(name = "FILE_ATTACHMENT")
public class FileAttachment implements java.io.Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	@Id
	@Column(name = "FILE_ID",nullable = false, length = 50)
	@OrderBy("FILE_ID asc")
	private String id;
	@Column(name = "MONGOFILE_ID",nullable = false, length = 50)
	private String mongoFileId;
	
	@Column(name = "CONTENT_TYPE",nullable = false, length = 50)
	private String contentType;
	
	@Column(name = "FILE_NAME",nullable = false, length = 100)
	private String fileName;
	
	@Column(name = "FILE_URL",nullable = false, length = 100)
	private String fileUrl;
	
	public FileAttachment() {
		super();
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getMongoFileId() {
		return mongoFileId;
	}

	public void setMongoFileId(String mongoFileId) {
		this.mongoFileId = mongoFileId;
	}

	public String getContentType() {
		return contentType;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getFileUrl() {
		return fileUrl;
	}

	public void setFileUrl(String fileUrl) {
		this.fileUrl = fileUrl;
	}
	
}

 

对应的增删改查就不写了

windows 打包 mongodb的服务 mongodb做文件服务器_spring

以此关联对应的业务表

dao层

/**
 * 
 *  @application name: 文件存储
 *  @author: zhouxinlei 
 *  @time:2018年9月21日
 *  @version:ver 1.1
 */
public interface MongoDBFileDao extends MongoRepository<MongoDBFile, String>{
	MongoDBFile findMongoDBFileById(String id);
}

继承org.springframework.data.mongodb.repository.MongoRepository

service层

public interface IMongoDBFileService {

	/**
     *	 保存文件
     * @param File
     * @return
     */
	MongoDBFile saveFile(MongoDBFile file);
    
    /**
     * 	删除文件
     * @param File
     * @return
     */
    void removeFile(String id);
    
    /**
     * 	根据id获取文件
     * @param File
     * @return
     */
    MongoDBFile getFileById(String id);

    /**
     * 	分页查询,按上传时间降序
     * @param pageIndex
     * @param pageSize
     * @return
     */
    List<MongoDBFile> listFilesByPage(int pageIndex, int pageSize);
    
}

service实现

@Service
public class MongoDBFileServiceImpl implements IMongoDBFileService {
	
	@Resource
	public MongoDBFileDao fileDao;
	
	@Override
	public MongoDBFile saveFile(MongoDBFile file) {
		return fileDao.save(file);
	}

	@Override
	public void removeFile(String id) {
		// TODO Auto-generated method stub
		fileDao.deleteById(id);
	}

	@Override
	public MongoDBFile getFileById(String id) {
		// TODO Auto-generated method stub
		return fileDao.findMongoDBFileById(id);
	}

	@Override
	public List<MongoDBFile> listFilesByPage(int pageIndex, int pageSize) {
		Page<MongoDBFile> page = null;
        List<MongoDBFile> list = null;
        Sort sort = new Sort(Direction.DESC,"uploadDate"); 
        Pageable pageable = new PageRequest(pageIndex, pageSize, sort);
        page = fileDao.findAll(pageable);
        list = page.getContent();
        return list;
	}

}

MongoDBFileController类

/**
 *  @application name: 文件存储
 *  @author: zhouxinlei 
 *  @time:2018年9月21日
 *  @version:ver 1.1
 */
@Controller
public class MongoDBFileController {
	
	@Autowired
    private IMongoDBFileService fileService;
	@Resource
    private IFileAttachmentService fileAttachmentService;
    @Value("${spring.data.mongodb.uri}")
    private String serverAddress;
    /**
     * 	分页查询文件
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @RequestMapping(value = "/findAllFiles", produces="application/json;charset=UTF-8",method = RequestMethod.GET)
    @ResponseBody
    public List<MongoDBFile> listFilesByPage(HttpServletResponse response, HttpServletRequest request){
        String pageIndex = request.getParameter("pageIndex");
        String pageSize = request.getParameter("pageSize");
    	return fileService.listFilesByPage(Integer.valueOf(pageIndex), Integer.valueOf(pageSize));
    }
    /**
     * 	获取文件片信息
     * @param id
     * @return
     */
    @RequestMapping(value = "/findFileInfo", produces="application/json;charset=UTF-8",method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Object> serveFile(HttpServletResponse response, HttpServletRequest request) {
    	String mongodbId = request.getParameter("mongodbId");
    	MongoDBFile file = fileService.getFileById(mongodbId);
        if (file != null) {
            return ResponseEntity
                    .ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; fileName=\"" + file.getName() + "\"")
                    .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream" )
                    .header(HttpHeaders.CONTENT_LENGTH, file.getSize()+"")
                    .header("Connection",  "close") 
                    .body( file.getContent());
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("文件找不到");
        }

    }
    /**
     * 	在线显示文件
     * @param id
     * @return
     */
    @RequestMapping(value = "/ViewFileOnLine", produces="application/json;charset=UTF-8",method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Object> serveFileOnline(HttpServletResponse response, HttpServletRequest request) {
    	String mongodbId = request.getParameter("mongodbId");
    	MongoDBFile file = fileService.getFileById(mongodbId);
        if (file != null) {
            return ResponseEntity
                    .ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "fileName=\"" + file.getName() + "\"")
                    .header(HttpHeaders.CONTENT_TYPE, file.getContentType() )
                    .header(HttpHeaders.CONTENT_LENGTH, file.getSize()+"")
                    .header("Connection",  "close") 
                    .body(file.getContent());
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("文件找不到");
        }
    }
    /**
     * 	上传接口
     * @param file
     * @return
     */
    @RequestMapping(value = "/uploadFile", produces="application/json;charset=UTF-8",method = RequestMethod.POST)
    @ResponseBody
    public void handleFileUpload(@RequestParam("file") MultipartFile file,HttpServletResponse response, HttpServletRequest request) {
    	String cs = "";
    	MongoDBFile returnFile = null;
        try {
        	MongoDBFile mongoDBFile = new MongoDBFile(file.getOriginalFilename(),  file.getContentType(), file.getSize(),file.getBytes());
        	mongoDBFile.setMd5( MD5Util.getMD5(file.getInputStream()) );
            returnFile = fileService.saveFile(mongoDBFile);
            FileAttachment fileAttachment = new FileAttachment();
        	fileAttachment.setId(returnFile.getId());
        	fileAttachment.setContentType(file.getContentType());
        	fileAttachment.setFileName(file.getOriginalFilename());
            fileAttachment.setMongoFileId(returnFile.getId());
            String fileUrl = request.getContextPath()+"/ViewFileOnLine?mongodbId="+returnFile.getId();
            fileAttachment.setFileUrl(fileUrl);
            fileAttachmentService.saveFileAttachment(fileAttachment);
            cs = ReturnMessage.messageData(ReturnMessage.SUCCESS, "上传成功!",fileAttachment);
        } catch (IOException | NoSuchAlgorithmException ex) {
            ex.printStackTrace();
            cs = ReturnMessage.messageData(ReturnMessage.FAIL, "上传失败!",null);
        }
        ControllerUtil.writejsonAndSession(response, request, cs);
    }
    /**
     * 	删除文件
     * @param id
     * @return
     */
    @RequestMapping(value="deleteMongoDBfile",produces="application/json;charset=UTF-8")
    @ResponseBody
    public void deleteFile(HttpServletResponse response, HttpServletRequest request) {
    	String mongodbId = request.getParameter("mongodbId");
    	String cs = "";
        try {
            fileService.removeFile(mongodbId);
            cs = ReturnMessage.messageData(ReturnMessage.SUCCESS, "删除文件成功!",null);
        } catch (Exception e) {
        	cs = ReturnMessage.messageData(ReturnMessage.SUCCESS, "删除文件失败!",null);
        }
        ControllerUtil.writejsonAndSession(response, request, cs);
    }
}

在保存文件时,同事保存关系表

windows 打包 mongodb的服务 mongodb做文件服务器_java_02

将文件存储的信息保存进去,返回ajax这个对象,

前台处理,我采用的是layUI支持的上传文档接口

<label class="layui-form-label">头像</label>
						<div class="layui-upload">
						  <button type="button" class="layui-btn" id="upload"><i class="layui-icon"></i>上传头像</button>
						  <img class="layui-upload-img" style="width: 10%;height: 10%;" id="uploadFile">
						  <span id="textMeaasge"></span>
						</div>

js

layui.use('upload', function(){
		var contextPath = getContextPath();
		var url = contextPath+"/uploadFile/";
	  	var upload = layui.upload;
	  	var $ = layui.jquery
	    ,upload = layui.upload;
	    //普通图片上传
	    var uploadInst = upload.render({
	      elem: '#upload'
	      ,url: url
	      ,before: function(obj){
	        obj.preview(function(index, file, result){
	          $('#uploadFile').attr('src', result);
	        });
	      }
	      ,done: function(res){
	        if(res.code < 0){
	          return layer.msg(res.message,{icon:2,shift: 6});
	        }else{
	        	var fileId = res.data.id;
	        	document.getElementById("fileId").value = fileId;
	        	var demoText = $('#textMeaasge');
	        	demoText.html('');
	        	return layer.msg(res.message,{icon:1,shift:6});
	        }
	      }
	      ,error: function(){
	        //失败状态,并实现重传
	        var demoText = $('#textMeaasge');
	        demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs reUpload">重试</a>');
	        demoText.find('.reUpload').on('click', function(){
	          uploadInst.upload();
	        });
	      }
	    });
	});

画面效果是这样

windows 打包 mongodb的服务 mongodb做文件服务器_java_03

windows 打包 mongodb的服务 mongodb做文件服务器_spring_04

windows 打包 mongodb的服务 mongodb做文件服务器_mongodb_05

windows 打包 mongodb的服务 mongodb做文件服务器_java_06

此处可以看见,文件已保存到mongodb中

接下来就是保存文件id

 

windows 打包 mongodb的服务 mongodb做文件服务器_mongodb_07

windows 打包 mongodb的服务 mongodb做文件服务器_java_08

至此,简单的文件存储就实现了,mongodb可视化工具我使用的是adminmongo,安装教程可自行百度

windows 打包 mongodb的服务 mongodb做文件服务器_mongodb_09