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

一、项目背景

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

1. 表单个附件共存

2. 只有附件

3. 只有表单

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

二、项目需求

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

三、项目架构

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

四、技术实现

4.1 数据库创建

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

25c69ebe666efa1579424926fe11d5d3.png

字段可以根据业务的不同适当添加,我做个例子,有这几个字段就够了,其中relationID是和我们的业务表管理的,主外键关联或者普通关联。下面是业务表的创建:

5fcbbd5f603f246212b167b4bbe91768.png

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

4.2 后台代码编写

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagecom.common.model;importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.GenerationType;importjavax.persistence.Id;importjavax.persistence.Table;

@Entity

@Table(name="tab_userinfo")public classTabUserinfo {

@Id

@GeneratedValue(strategy=GenerationType.AUTO)private intid;privateString username;privateString password;privateString relationID;privateString remark;publicTabUserinfo() {super();

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

}public intgetId() {returnid;

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

}publicString getUsername() {returnusername;

}public voidsetUsername(String username) {this.username =username;

}publicString getPassword() {returnpassword;

}public voidsetPassword(String password) {this.password =password;

}publicString getRelationID() {returnrelationID;

}public voidsetRelationID(String relationID) {this.relationID =relationID;

}publicString getRemark() {returnremark;

}public voidsetRemark(String remark) {this.remark =remark;

}

@OverridepublicString toString() {return "TabUserinfo [id=" + id + ", username=" + username + ", password=" + password + ", relationID="

+ relationID + ", remark=" + remark + "]";

}

}packagecom.common.model;importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.GenerationType;importjavax.persistence.Id;importjavax.persistence.Table;

@Entity

@Table(name="tab_userinfo")public classTabUserinfo {

@Id

@GeneratedValue(strategy=GenerationType.AUTO)private intid;privateString username;privateString password;privateString relationID;privateString remark;publicTabUserinfo() {super();

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

}public intgetId() {returnid;

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

}publicString getUsername() {returnusername;

}public voidsetUsername(String username) {this.username =username;

}publicString getPassword() {returnpassword;

}public voidsetPassword(String password) {this.password =password;

}publicString getRelationID() {returnrelationID;

}public voidsetRelationID(String relationID) {this.relationID =relationID;

}publicString getRemark() {returnremark;

}public voidsetRemark(String remark) {this.remark =remark;

}

@OverridepublicString toString() {return "TabUserinfo [id=" + id + ", username=" + username + ", password=" + password + ", relationID="

+ relationID + ", remark=" + remark + "]";

}

}

View Code

文件上传:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

@CrossOrigin(origins = "*", maxAge = 3600)

@Controller

@RequestMapping("user")public classUserController {protected Logger log = Logger.getLogger(UserController.class);

@Autowired

ServiceI service;

@RequestMapping(value="userAddFile",produces = {"application/json;charset=UTF-8"},method=RequestMethod.POST)

@ResponseBodypublic String addFile(TabUserinfo userinfo,@RequestParam(value="file",required=true) MultipartFile [] uploadFile,

HttpServletRequest request){

JSONObject jsonRusult=newJSONObject();

String UUIDString=UUID.randomUUID().toString();

String date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(newDate());boolean flag=false;

List 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);

}returnJSON.toJSONString(jsonRusult,SerializerFeature.WriteMapNullValue);

}

View Code

文件上传工具类:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public static ListuploadFile(ServiceI service,String relationID,String date, MultipartFile [] uploadFile,HttpServletRequest request)throwsIllegalStateException, IOException{

ServletContext servletContext=request.getServletContext();

List fileList=new ArrayList<>();

UploadFile fileEntity=null;for(int i=0;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=newFile(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("文件不存在");;

}

}

}returnfileList;

}/*** 保存文件信息

*@paramfileName

*@paramfilePath*/

private staticUploadFile saveFileInfo(ServiceI service,String fileName,String filePath,String relationID, String date) {

UploadFile fileEntity=newUploadFile();

fileEntity.setFileName(fileName);

fileEntity.setFilePath(filePath);

fileEntity.setRelationID(relationID);

fileEntity.setUploadTime(date);

service.saveOrUpdate(fileEntity);returnfileEntity;

}

View Code

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

7c648e0859efd53b415683f3f1ff9156.png

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

19d6c6e54473e9618c319d3469194015.png

文件路径找不到

2b5bfb99a508432ca60e01dfd4e9e9eb.png

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

4.3 Postman进行测试:

60a5dc5fde6de1e25959289263b4314a.png

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

a50d3c959e1f298969365c42cc2d355d.png

025c6d4f1ade2651a1ddbdb2e5855432.png

证明我们的接口是好用的,这里解释下为什么要返回文件的相关信息,因为对于图片来说,我们会上传完成显示预览图,对于文件来说返回链接,可以下载查看等,因此这么返回的路径。在前段中配置SRC就可以进行下载操作

如下图:

我们把链接复制进浏览器首先看图的:

d3449e477952ce8809fd679daad85cba.png

再来看文件的:

452b00bd9d4bebe3b39949510d9b3ca6.png

这样可以方便我们对文件进行后续的操作。

下面来说正事,我在这个项目上面才过的坑,希望大家引以为戒,不要掉进去。

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服务上,上传的文件就可以在我们服务器部署的位置找到,我采取的就是这种方式:

d09b3afddd232313b743539d66289814.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 返回下载流的二进制

*@parampath

*@return*@throwsUnsupportedEncodingException*/

public static ResponseEntitygetStreamByPath(String filePath,HttpServletRequest request,

HttpServletResponse response,String fileName)throwsUnsupportedEncodingException {

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 entity=null;

InputStream is=null;try{//url=new URL(filePath);//System.out.println(url.toString());//File file=new File(url.getPath());

File file=newFile(filePath);if(file.exists()){

String mimeType=URLConnection.guessContentTypeFromName(fileName);if(mimeType==null){

mimeType= "application/octet-stream";

}

response.setContentType(mimeType);byte[] body = null;

is= newFileInputStream(file);

body= new byte[is.available()];

is.read(body);

HttpHeaders headers= newHttpHeaders();

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(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();

}

}

}returnentity;

}

View Code

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 文件删除

*@parampath

*@return*@throwsUnsupportedEncodingException*/

public static booleandeleteFile(String filePath,HttpServletRequest request,

HttpServletResponse response,String fileName)throwsUnsupportedEncodingException {boolean flag=false;if(StringUtil.isNull(fileName,filePath)){

File file=newFile(filePath);if(file.exists()){

flag=file.delete();

}

}returnflag;

}

View Code

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

最后附上相关配置文件:

1.  SpringMVC.xml

97b2cbff98cf0098df661a2c8990e06a.png

2. web.xml

5ebc438b141a30ea24c7bff6fa0d25b5.png

五、总结

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值