实现文件的上传,本质上就是将用户电脑上的文件复制到服务器上所在的电脑上
开发思路:
- 1,建立和上传源文件有关的输入流;
文件上传过程中的输入流,要通过request对象获取 - 2,建立和目标服务器文件关联的输出流
输出文件,就是想Action所在的电脑上写入一个文件 - 3,一边读一遍写。
- 4,关闭输入输出流
需要注意的是,request.getInputStream()得到的输入流本身包含上传的文件还有一些附加信息(比如文件类型、文件大小、文件名等)
通常我们不会直接使用输入流,而是借助第三方jar包完成文件上传
比如:commons-fileupload-1.3.1.jar就对文件的上传操作做了很好的封装,
struts2再一次对fileupload.jar做了封装,简化文件的上传操作。
开发步骤,
先开看一下项目的整个目录结构:
1. 上传文件的页面 upload.jsp
注意,form表单的enctype="multipart/form-data"这句话一定要写,否则无法上传
${pageContext.request.contextPath }是获取项目路径
<form action="${pageContext.request.contextPath }/file/upload" method="post" enctype="multipart/form-data"> <input type="file" name="fillup"><br /> <input type="submit"> </form>
2. 开发Action
项目导包import配置没有写,可crtl+shift+O一键导包
/** * @author 超伟 * @2019年6月26日 下午2:13:29 * @博客:https://blog.csdn.net/MacWx */ public class FileAction implements RequestAware { private Map<String, Object> request; // 1,获取文件 private File fillup; // 获取文件名; private String fillupFileName; // 获取文件类型 private String fillupContentType; // in private Integer id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } // out private List<Fileupload> list; public List<Fileupload> getList() { return list; } public void setList(List<Fileupload> list) { this.list = list; } public File getFillup() { return fillup; } public void setFillup(File fillup) { this.fillup = fillup; } public String getFillupFileName() { return fillupFileName; } public void setFillupFileName(String fillupFileName) { this.fillupFileName = fillupFileName; } public String getFillupContentType() { return fillupContentType; } public void setFillupContentType(String fillupContentType) { this.fillupContentType = fillupContentType; } public String FileUp() { FileInputStream fis = null; FileOutputStream fos = null; BufferedInputStream bis = null; BufferedOutputStream bos = null; try { // 创建文件输入流 fis = new FileInputStream(fillup); // 创建包装流,加快文件上传速度 bis = new BufferedInputStream(fis); System.out.println("name= " + fillupFileName); System.out.println("type= " + fillupContentType); // 获取request对象 HttpServletRequest request = ServletActionContext.getRequest(); ServletContext context = request.getServletContext(); // 创建文件路径,文件对应的文件类型放入对应的文件夹下 String path = "/file"; if (fillupContentType.equals("text/plain")) { path = "/file/text"; } else if (fillupContentType.equals("image/png") || fillupContentType.equals("image/jpg")) { path = "/file/img"; } else if (fillupContentType.equals("application/msword")) { path = "/file/word"; } else if (fillupContentType.equals("application/zip")) { path = "/file/zip"; } else if (fillupContentType.equals("application/x-msdownload")) { path = "/file/exe"; } //如果对应放的文件夹不存在,则创建! String realPath = context.getRealPath(path); File filePath = new File(realPath); if (!filePath.exists()) { // 不存在 filePath.mkdirs(); } //System.out.println("realPath= " + realPath); System.out.println("filePath= " + filePath); // 新建输出流 fos = new FileOutputStream(realPath + "\\" + fillupFileName); bos = new BufferedOutputStream(fos); // 3,边读边写 while (true) { int read = bis.read(); if (read == -1) { break; } bos.write(read); } // 调用service方法,将文件名,文件路径等存入数据库 FileService service = new FileServiceImpl(); Fileupload f = new Fileupload(null, fillupContentType,"/"+fillupFileName, path, null); service.upFile(f); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { // 4,关闭流 try { bis.close(); bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return "success"; } }
注意:根据相对项目的路径地址,获取一个文件的绝对路径,要使用servletContext.getRealPath(“/相对项目根目录的路径”);
service实现类方法如下:FileServiceImpl.java
package com.macw.service.impl; import java.sql.Connection; import java.sql.SQLException; import java.util.List; import com.macw.dao.FileDao; import com.macw.dao.impl.FileDaoImpl; import com.macw.entity.Fileupload; import com.macw.service.FileService; import com.macw.util.JdbcUtil; /** * @author 超伟 * @2019年6月26日 下午2:11:37 * @博客:https://blog.csdn.net/MacWx */ public class FileServiceImpl implements FileService { /* (non-Javadoc) * @see com.macw.service.FileService#upFile(com.macw.entity.File) */ public void upFile(Fileupload f) { // TODO Auto-generated method stub Connection conn = JdbcUtil.getConnection(); try { conn.setAutoCommit(false); FileDao dao = new FileDaoImpl(); dao.upFile(f); conn.commit(); } catch (SQLException e) { // TODO Auto-generated catch block try { conn.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); }finally{ JdbcUtil.toClose(conn, null, null); } }
对应的Dao数据操作层dao的实现类如下:FileDaoImpl.java
public class FileDaoImpl implements FileDao { /* (non-Javadoc) * @see com.macw.dao.FileDao#upFile(com.macw.entity.File) */ @Override public void upFile(Fileupload f) { // TODO Auto-generated method stub try { JdbcUtil.update("insert into t_file values (seq_file.nextval,?,?,?,?)",f.getFile_content_type(),f.getFile_name(),f.getFile_path(),f.getUSER_ID()); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
实体类:Fileupload
其中属性和数据表的字段是一一对应的
public class Fileupload { //file id private Integer file_id; //文件类型 private String file_content_type; //文件名 private String file_name; // 文件路径 private String file_path; // 用户id 操作人 private Integer USER_ID; getter() && setter()方法,构造方法,省略不写
二次更新,
想起来struts2框架对上传文件大小的默认限制为2m。
所以要设置struts.xml来修改默认的上传限制,
<struts> <!-- 将上传文件大小限制改为20M --> <constant name="struts.multipart.maxSize" value="20971520"></constant> <package name="file" extends="struts-default" namespace="/file"> <action name="upload" class="com.macw.action.FileAction" method="FileUp"> <result name="success" type="redirectAction">selall</result> </action> <action name="selall" class="com.macw.action.FileAction" method="SelAllFile"> <result name="success">/upload.jsp</result> </action> <action name="download" class="com.macw.action.FileAction" method="Download"> </action> </package> </struts>
如此,就实现了文件的上传操作,对应的项目源码地址为: