基于SpringMVC的文件(增删改查)上传、下载、更新、删除

1、项目背景 

  摘要:最近一直在忙着项目的事,3个项目过去了,发现有一个共同的业务,那就是附件的处理,附件包括各类文档,固然还有图片等特殊文件,因为时间的关系,每次都是匆匆忙忙的搞定上线,称这项目的空档,整理了一份附件上传、下载、删除的项目,主要就是附件的处理,状况包含如下几种:java

  1. 表单个附件共存web

  2. 只有附件数据库

  3. 只有表单编程

其中,后两种处理方式简单,本文主要说明的是第一种的处理方案。json

2、项目需求

  总体来讲,项目需求仍是不复杂的,这里单独把附件和表单数据提交拿出来讲,就是表单中的有附件的状况,表单中的附件随时能够进行替换、删除、添加等操做。折腾了好久,终于把附件上传这档子事理清楚了,这里作个记录,与各位大神共勉。浏览器

3、项目架构

  项目架构采用的是比较经常使用的传统的javaWeb项目开发框架,Spring4.3.4,hibernate5(ssh),MySQL 5.7,Tomcat7.0,关于该项目的如何整合,就再也不多说了,网上都有,搭建一套框架,应该不是问题。该业务实现的思想就是:数据库存放文件路径,这里是物理路径,注意物理路径和虚拟路径的区别,文件存放在服务器,须要的时候经过数据库表中的物理路径能够找到相应的文件,增删改查都是能够的。服务器

4、技术实现

 4.1 数据库建立

  打开MySQL管理工具或者CMD dos界面进入MySQL建立数据库,这里,我使用管理工具建立的,首先是文件表:架构

  

 

  字段能够根据业务的不一样适当添加,我作个例子,有这几个字段就够了,其中relationID是和咱们的业务表管理的,主外键关联或者普通关联。下面是业务表的建立:app

  

 

数据库表大概就是这样,附件表和业务表关联,固然关联的方式有不少,我只选择了最简单的主外键关联。框架

4.2 后台代码编写

  项目架构使用的hibernate,hibernate主要的有点就是基于对象,很是适合面向对象编程的本质,下面建立对象,采用Spring注解的方式:

package com.common.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="tab_userinfo")
public class TabUserinfo {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String username;
    private String password;
    private String relationID;
    private String remark;
    
    public TabUserinfo() {
        super();
    }

    public TabUserinfo(int id, String username, String password, String remark) {
        super();
        this.id = id;
        this.username = username;
        this.password = password;
        this.remark = remark;
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRelationID() {
        return relationID;
    }

    public void setRelationID(String relationID) {
        this.relationID = relationID;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Override
    public String toString() {
        return "TabUserinfo [id=" + id + ", username=" + username + ", password=" + password + ", relationID="
                + relationID + ", remark=" + remark + "]";
    }

    

    
    
    
    
    
    
}
package com.common.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="tab_userinfo")
public class TabUserinfo {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String username;
    private String password;
    private String relationID;
    private String remark;
    
    public TabUserinfo() {
        super();
    }

    public TabUserinfo(int id, String username, String password, String remark) {
        super();
        this.id = id;
        this.username = username;
        this.password = password;
        this.remark = remark;
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRelationID() {
        return relationID;
    }

    public void setRelationID(String relationID) {
        this.relationID = relationID;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Override
    public String toString() {
        return "TabUserinfo [id=" + id + ", username=" + username + ", password=" + password + ", relationID="
                + relationID + ", remark=" + remark + "]";
    }

    
}
View Code

文件上传:

@CrossOrigin(origins = "*", maxAge = 3600)
@Controller
@RequestMapping("user")
public class UserController {
    protected Logger log = Logger.getLogger(UserController.class);
    @Autowired
    ServiceI service;
    
    @RequestMapping(value="userAddFile",produces = {"application/json;charset=UTF-8"},method=RequestMethod.POST)
    @ResponseBody
    public String addFile(TabUserinfo userinfo,@RequestParam(value="file",required=true) MultipartFile [] uploadFile,
            HttpServletRequest request){    
        
        JSONObject jsonRusult=new JSONObject();
        String UUIDString=UUID.randomUUID().toString();
        String date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        boolean flag=false;
        List<Object> fileList=null;
        ReturnStatus rStatus=null;
        log.info("UUID:"+UUIDString);
        //保存表单数据
        try {
            if(null!=userinfo){
                log.info("数据userinfo:"+userinfo.toString());
                userinfo.setRelationID(UUIDString);
                service.saveOrUpdate(userinfo);
                flag=true;
            }
            if(flag){
                //上传附件
                fileList=FileUtils.uploadFile(service, UUIDString, date, uploadFile, request);
            }
            if(null!=fileList && fileList.size()!=0){
                rStatus=new ReturnStatus("0000", "文件上传成功!");
                jsonRusult.put("status", rStatus);
                jsonRusult.put("fileInfo", fileList);
            }else{
                rStatus=new ReturnStatus("0003", "文件上传失败!");
                jsonRusult.put("fileInfo", null);
            }
            
        } catch (IllegalStateException e) {
            log.error("文件上传失败",e);
            service.delete(userinfo);//保证事务
        } catch (IOException e) {
            log.error("文件上传失败",e);
            service.delete(userinfo);
        }
        
        return JSON.toJSONString(jsonRusult,SerializerFeature.WriteMapNullValue);
    }
View Code

文件上传工具类:

public static List<Object> uploadFile(ServiceI service,String relationID,String date, MultipartFile [] uploadFile,HttpServletRequest request) 
            throws IllegalStateException, IOException{
        
        ServletContext servletContext = request.getServletContext();
        List<Object> fileList=new ArrayList<>();
        UploadFile fileEntity=null;
        for(int i=0;i<uploadFile.length;i++){
            String filePath= servletContext.getRealPath("/upload");
            log.info("文件存放磁盘路径:"+filePath);
            String rePath=request.getScheme()+"://"+request.getServerName()+":"+
                    request.getServerPort()+request.getContextPath()+"/upload";
            log.info("取文件路径:"+rePath);
            MultipartFile file=uploadFile[i];
            String fileName=file.getOriginalFilename();
            String fileNameS="";
            String fileType=fileName.split("\\.")[fileName.split("\\.").length-1];
            if(StringUtil.isNull(fileName,fileType)){
                fileNameS=UUID.randomUUID()+"."+fileType;
                if(!file.isEmpty()){
                    if(fileType.contains("jpg") || fileType.contains("png") || fileType.contains("gif")){
                        filePath+="\\image\\"+fileNameS;
                        rePath+="/image/"+fileNameS;
                    }else{
                        filePath+="\\file\\"+fileNameS;
                        rePath+="/file/"+fileNameS;
                    }
                    log.info("文件路径filePath:"+filePath);
                    log.info("文件路径rePath:"+rePath);
                    File fileS=new File(filePath);
                    if(!fileS.getParentFile().exists()){
                        fileS.getParentFile().mkdirs();
                    }
                    file.transferTo(fileS);
                    
                    fileEntity=saveFileInfo(service,fileName,filePath,relationID,date);
                    if(null!=fileEntity){
                        fileEntity.setFilePath(rePath);
                        fileList.add(fileEntity);
                    }
                    
                }else{
                    fileList.add("文件不存在");;
                }
            }
        }
        return fileList;
    }
    /**
     * 保存文件信息
     * @param fileName
     * @param filePath
     */
    private static UploadFile saveFileInfo(ServiceI service,String fileName,String filePath,String relationID, String date) {
        
        UploadFile fileEntity=new UploadFile();
        fileEntity.setFileName(fileName);
        fileEntity.setFilePath(filePath);
        fileEntity.setRelationID(relationID);
        fileEntity.setUploadTime(date);
        service.saveOrUpdate(fileEntity);
        return fileEntity;
    }
View Code

这里须要注意的是:在多文件上上传的时候必定要注意,文件路径的获取,必定是每一个文件获取一次,以下图:

若是一次性获取,会发生意外:如图

文件路径找不到

 这样只能上传第一个文件,并且业务表中没有成功插入数据。 

4.3 Postman进行测试:

下面咱们再来看数据库中是否有数据

  证实咱们的接口是好用的,这里解释下为何要返回文件的相关信息,由于对于图片来讲,咱们会上传完成显示预览图,对于文件来讲返回连接,能够下载查看等,所以这么返回的路径。在前段中配置SRC就能够进行下载操做

以下图:

咱们把连接复制进浏览器首先看图的:

再来看文件的:

这样能够方便咱们对文件进行后续的操做。

   下面来讲正事,我在这个项目上面才过的坑,但愿你们引觉得戒,不要掉进去。

  1. 文件上传路径

  由于咱们的项目是在Eclipse上进行开发测试的,所以上传的文件会存在Eclipse工做空间中去,存到工做空间以后,在E:\workspace\eclipse_workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\webapps下,是没有权限访问的,所以读取文件的时候会报错,因此最好的办法就是制定一个本地服务器的物理路径,而后经过Tomcat中的server.xml 进行配置映射,存到服务其中的物理路径是:E:\service\webapps\common\upload\file\fd6e9dfb-7d1c-4fc6-8954-851258f6acc4.doc,那么只要咱们开启的Tomcat服务,就能够经过:IP/common/upload/file/fd6e9dfb-7d1c-4fc6-8954-851258f6acc4.doc访问到咱们上传的文件。其中common是项目名称,upload是指定上传的文件夹。

  另外一种状况,咱们能够直接把项目打成war包部署在Tomcat服务上,上传的文件就能够在咱们服务器部署的位置找到,我采起的就是这种方式:

  固然了,咱们也能够经过接口的方式对文件进项下载,思想就是:经过相关条件找到数据库中存放的文件路径,拿到文件路径生成文件以二进制的方式返回给浏览器。下面是采用SpringMVC开发的下载文件接口:

/**
     * 返回下载流的二进制
     * @param path
     * @return
     * @throws UnsupportedEncodingException 
     */
    public static ResponseEntity<byte[]> getStreamByPath(String filePath,HttpServletRequest request,
            HttpServletResponse response,String fileName) throws UnsupportedEncodingException {
        
         response.setCharacterEncoding("utf-8");
         response.setContentType( "application/x-msdownload");
         response.addHeader("Content-Disposition","attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));// 设置文件名
         System.out.println("fdsfdsfsdf:"+filePath);
        URL url=null;
        ResponseEntity<byte[]> entity=null;
        InputStream is =null;
        try {
//            url=new URL(filePath);
            
//            System.out.println(url.toString());
//            File file=new File(url.getPath());
            File file=new File(filePath);
            if(file.exists()){
                String mimeType = URLConnection.guessContentTypeFromName(fileName);
                if(mimeType==null){
                    mimeType = "application/octet-stream";
                }
                response.setContentType(mimeType);
                byte[] body = null;
                is = new FileInputStream(file);
                body = new byte[is.available()];
                is.read(body);
                HttpHeaders headers = new HttpHeaders();
                headers.add("Content-Disposition", "attchement;filename="+ URLEncoder.encode(fileName, "UTF-8"));
                HttpStatus statusCode = HttpStatus.OK;
                headers.setContentDispositionFormData("attachment", file.getName());     
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);   
                entity = new ResponseEntity<byte[]>(body, headers, statusCode);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
         return entity;
    }
View Code

下面是文件删除,文件删除其实很简单了,咱们按照相关条件找到文件,而后删除便可。

/**
     * 文件删除
     * @param path
     * @return
     * @throws UnsupportedEncodingException 
     */
    public static boolean deleteFile(String filePath,HttpServletRequest request,
            HttpServletResponse response,String fileName) throws UnsupportedEncodingException {
        boolean flag=false;
        if(StringUtil.isNull(fileName,filePath)){
            File file=new File(filePath);
            if(file.exists()){
                flag=file.delete();
            }
        }
        
        return flag;
        
    }
View Code

切记:删除文件和数据库中的记录必定是一个事务,删除记录的同时删除数据库中的记录,不然会出现数据不一致的状况。

最后附上相关配置文件:

1.  SpringMVC.xml

2. web.xml

 

5、总结

  在作这些项目的时候,遇到的文件上传的坑大概就这么多,目前想到的附件上传只有这一种方式,你们若是有什么好的方法,欢迎评论区讨论!

 

       源码下载: https://download.csdn.net/download/qq_42389242/10746764

相关文章
相关标签/搜索