JavaWeb_文件上传下载_fileupload案例

来源:互联网 发布:奥登生涯数据 编辑:程序博客网 时间:2024/05/30 23:47

说明位于src类下面

javaweb工程:上传下载案例1,导包:共10个mysql驱动mysql-connector-java-5.0.8-bin.jarc3po连接池c3p0-0.9.2-pre1.jarmchange-commons-0.2.jardbutils操作数据库commons-dbutils-1.2.jarjstl开发库jstl.jarstandard.jarbeanUtils开发包及其依赖的log4j开发包commons-beanutils-1.8.0.jarcommons-logging.jarfileupload组件及其依赖的IO包commons-fileupload-1.2.1.jarcommons-io-1.4.jar2 创建组织程序的包3 准备库和表mysql -uroot -prootset character_set_client=gb2312;set character_set_results=gb2312;create database day18 character set utf8 collate utf8_general_ci;use day18;create table upfile(id varchar(40) primary key,        使用UUID算法生成(36位),便于扩展uuidname varchar(100) not null unique,形如X-X-X-X.txtfilename varchar(100) not null,形如a.txtsavepath varchar(255) not null,形如C:\...\day18_upload\WEB-INF\upload\15\4uptime datetime not null,description varchar(255),username varchar(40) not null通常应该是外键列)character set utf8 collate utf8_general_ci;2.做实体domain包下Upfile类代表实体成员:String id,uuidname,filename,savepath,Date uptime,decription,username,getter&setter3.做dao(为与service解耦,工厂模式)dao.impl包UpfileDaoImpl方法:void add(Upfile)方法:List<Upfile> getAll()实际开发要用分页完成方法:Upfile find(id)方法:void update(Upfile)方法:void delete(id)3.1用DbUtils简化开发,QueryRunner构造时需要连接池DataSource建个工具类JdbcUtils提供C3P0根据配置文件c3p0-config.xml生成的连接池4.做DaoFactory(为与service解耦,工厂模式)在factory包下建一个DaoFactory单例:构造私有化,自已new,提供公开方法获取读配置文件 dao.properties#key是接口的simpleName,value是实现类的完整名称UpfileDao=cn.itcast.dao.impl.UpfileDaoImpl泛型方法public <T> T createDao(Class<T> interfaceClass)5.做service层薄薄的业务层,内部维护了一个私有成员dao,所有功能调用dao工厂产生的dao实现类的实例完成6.做web层(从index.jsp开始) request.getContextPath();    /day18_upload    request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";    http://localhost:8080/day18_upload/ 


dao.properties位于src类下面

#key是接口的simpleName,value是实现类的完整名称UpfileDao=cn.itcast.dao.impl.UpfileDaoImpl


c3p0-config.xml位于src类下面


<?xml version="1.0" encoding="UTF-8"?><c3p0-config><default-config><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/day18</property><property name="user">root</property><property name="password">root</property><property name="acquireIncrement">5</property><property name="initialPoolSize">10</property><property name="minPoolSize">5</property><property name="maxPoolSize">20</property></default-config><named-config name="pre_eminent"><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/day18</property><property name="user">root</property><property name="password">root</property><property name="acquireIncrement">5</property><property name="initialPoolSize">10</property><property name="minPoolSize">5</property><property name="maxPoolSize">20</property></named-config></c3p0-config>


Upfile位于domain包

package cn.itcast.domain;import java.util.Date;/*mysql -uroot -prootset character_set_client=gb2312;set character_set_results=gb2312;create database day18 character set utf8 collate utf8_general_ci;use day18;create table upfile(id varchar(40) primary key,        使用UUID算法生成(36位),便于扩展uuidname varchar(100) not null unique,形如X-X-X-X.txtfilename varchar(100) not null, 形如a.txtsavepath varchar(255) not null, 形如C:\\...\\day18_upload\\WEB-INF\\upload\\15\\4uptime datetime not null,description varchar(255),username varchar(40) not null通常应该是外键列)character set utf8 collate utf8_general_ci;*///成员:String id,uuidname,filename,savepath,Date uptime,decription,username,getter&setterpublic class Upfile {String id;String uuidname;   String filename;   String savepath;   Date uptime;   String description;   String username;   public String getId() {      return id;   }   public void setId(String id) {      this.id = id;   }   public String getUuidname() {      return uuidname;   }   public void setUuidname(String uuidname) {      this.uuidname = uuidname;   }   public String getFilename() {      return filename;   }   public void setFilename(String filename) {      this.filename = filename;   }   public String getSavepath() {      return savepath;   }   public void setSavepath(String savepath) {      this.savepath = savepath;   }   public Date getUptime() {      return uptime;   }   public void setUptime(Date uptime) {      this.uptime = uptime;   }   public String getDescription() {      return description;   }   public void setDescription(String description) {      this.description = description;   }   public String getUsername() {      return username;   }   public void setUsername(String username) {      this.username = username;   }}



JdbcUtils位于utils包

package cn.itcast.utils;import java.sql.Connection;import java.sql.SQLException;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;/*用DbUtils简化开发,QueryRunner构造时需要连接池DataSource建个工具类JdbcUtils提供C3P0根据配置文件c3p0-config.xml生成的连接池下面是关于删除时,工具类提供的方法1,定义一个成员!线程局部 (thread-local) 变量2,提供获取(绑定在当前线程上的)连接的方法3,提供(绑定在当前线程上的连接的)开启事务的方法4,提供(绑定在当前线程上的连接的)提交事务的方法5,提供释放连接(并从当前线程中移除该连接)的方法*/public class JdbcUtils {   //线程局部 (thread-local) 变量   private static ThreadLocal<Connection> threadLocal=new ThreadLocal<Connection>();    //定义成员DataSource记住C3P0创建出来的数据源(即连接池)   private static DataSource ds;   static{      //用类成员DataSource记住根据配置文件创建出来的连接池!      ds=new ComboPooledDataSource();   }   public static DataSource getDataSource(){      return ds;   }   // 事务方法1:获取绑定在当前线程上的连接!   //如果没有,从池中取出一个绑定到当前线程!   public static Connection getConnection() {      Connection conn;      try {          //本方法的目的是:得到当前线程上绑定的连接         conn=threadLocal.get();         if (conn==null) {         //如果当前线程上还没有绑定连接(如线程范围内的首次获取)            //就从DBCP连接池中取出一个连接,并绑定到当前线程上,供线程上后面的dao使用!         conn=ds.getConnection();         threadLocal.set(conn);         }          //返回绑定在当前线程的连接,目的达到!         return conn;      } catch (SQLException e) {         throw new RuntimeException(e);      }   }   //ThreadLocal处理事务,静态方法2:开启事务   //获得当前线程上绑定的连接,并开启事务   public static void startTransaction() {      Connection conn;      conn=JdbcUtils.getConnection();      try {          //此时当前线程上必定绑定了连接,开启事务!         conn.setAutoCommit(false);      } catch (SQLException e) {         throw new RuntimeException(e);      }   }   //ThreadLocal处理事务,静态方法3:提交事务   public static void commitTransaction() {      //获得当前线程上绑定的连接,并提交事务      Connection conn;      conn=JdbcUtils.getConnection();      try {         //得到当前线程上绑定的连接并提交事务         conn.commit();      } catch (SQLException e) {         throw new RuntimeException(e);      }   }   //ThreadLocal处理事务,静态方法3:关闭连接,并解除绑定!千万注意!   //释放当前线程上绑定的连接,即归还给连接池!   public static void freeConnection() {      Connection conn;      conn=JdbcUtils.getConnection();      try {         conn.close();      } catch (SQLException e) {         throw new RuntimeException(e);      }finally{          //千万记得关闭连接时,要解除线程上绑定的连接            //从threadlocal容器(map<线程名,连接>)中移除对应当前线程的连接         threadLocal.remove();      }   }}



UpfileDaoImpl位于dao.impl包

package cn.itcast.dao.impl;import java.sql.SQLException;import java.util.List;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;import org.apache.commons.dbutils.handlers.BeanListHandler;import cn.itcast.dao.UpfileDao;import cn.itcast.domain.Upfile;import cn.itcast.exception.DaoException;import cn.itcast.utils.JdbcUtils;/*做dao(为与service解耦,工厂模式dao.impl包UpfileDaoImpl方法:void add(Upfile)方法:List<Upfile> getAll()实际开发要用分页完成方法:Upfile find(id)方法:void update(Upfile)方法:void delete(id)3.1用DbUtils简化开发,QueryRunner构造时需要连接池DataSource建个工具类JdbcUtils提供连接池*//*库和表mysql -uroot -prootset character_set_client=gb2312;set character_set_results=gb2312;create database day18 character set utf8 collate utf8_general_ci;use day18;create table upfile(id varchar(40) primary key,        使用UUID算法生成(36位),便于扩展uuidname varchar(100) not null unique,形如X-X-X-X.txtfilename varchar(100) not null,形如a.txtsavepath varchar(255) not null,形如C:\\...\\day18_upload\\WEB-INF\\upload\\15\\4uptime datetime not null,description varchar(255),username varchar(40) not null通常应该是外键列)character set utf8 collate utf8_general_ci;*/public class UpfileDaoImpl implements UpfileDao {   /* (non-Javadoc)    * @see cn.itcast.dao.impl.UpfileDao#add(cn.itcast.domain.Upfile)    */   public void add(Upfile f){      //操作数据库,不管三七二十一,先new 个QueryRunner      QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());      String sql="insert into upfile(id,uuidname,filename,savepath,uptime,description,username) values(?,?,?,?,?,?,?)";      Object[] params={f.getId(),f.getUuidname(),f.getFilename(),f.getSavepath(),f.getUptime(),f.getDescription(),f.getUsername()};      try {         qr.update(sql, params);      } catch (SQLException e) {         //有异常,抓,抛自定义DAO异常         throw new DaoException(e);      }   }   /* (non-Javadoc)    * @see cn.itcast.dao.impl.UpfileDao#find(java.lang.String)    */   public Upfile find(String id){      try {         //操作数据库,不管三七二十一,先new 个QueryRunner         QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());         String sql="select * from upfile where id=?";         return (Upfile) qr.query(sql, id, new BeanHandler(Upfile.class));      } catch (Exception e) {         //有异常,抓,抛自定义DAO异常         throw new DaoException(e);      }   }   //实际开发中,要用分而查询    /* (non-Javadoc)    * @see cn.itcast.dao.impl.UpfileDao#getAll()    */   public List<Upfile> getAll(){      try {         //操作数据库,不管三七二十一,先new 个QueryRunner         QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());         //根据上传时间降序排列         String sql="select * from upfile order by uptime desc";         return (List<Upfile>) qr.query(sql, new BeanListHandler(Upfile.class));      } catch (Exception e) {         //有异常,抓,抛自定义DAO异常         throw new DaoException(e);      }   }   /* (non-Javadoc)    * @see cn.itcast.dao.impl.UpfileDao#update(cn.itcast.domain.Upfile)    */   public void update(Upfile f){      //操作数据库,不管三七二十一,先new 个QueryRunner      QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource());      String sql="update upfile set uuidname=?,filename=?,savepath=?,uptime=?,description=?,username=? where id=?";      Object[] params={f.getUuidname(),f.getFilename(),f.getSavepath(),f.getUptime(),f.getDescription(),f.getUsername(),f.getId()};      try {         qr.update(sql, params);      } catch (SQLException e) {         //有异常,抓,抛自定义DAO异常         throw new DaoException(e);      }   }   //因为删除记录和删除文件是同一个事务里面的!   //所以删除操作 必须使用JdbcUtils获取连接!   //即JdbcUtils获取绑定在当前线程上的连接!如果没有,从池中取出一个绑定到当前线程!   public void delete(String id){      try {         //操作数据库,不管三七二十一,先new 个QueryRunner         //new的时候,不能传连接池给它了,因后面要自己控制事务提交         QueryRunner qr=new QueryRunner();         String sql="delete from upfile where id=?";         qr.update(JdbcUtils.getConnection(), sql, id);      } catch (Exception e) {         //有异常,抓,抛自定义DAO异常         throw new DaoException(e);      }   }}



UpfileDao位于dao包

package cn.itcast.dao;import java.util.List;import cn.itcast.domain.Upfile;public interface UpfileDao {   public abstract void add(Upfile f);   public abstract Upfile find(String id);   //实际开发中,要用分而查询    public abstract List<Upfile> getAll();   public abstract void update(Upfile f);   public abstract void delete(String id);}



DaoFactory位于factory包

package cn.itcast.factory;import java.io.IOException;import java.io.InputStream;import java.util.Properties;import cn.itcast.exception.DaoException;/*为与service解耦,工厂模式)在factory包下建一个DaoFactory单例:构造私有化,自已new,提供公开方法获取读配置文件 dao.properties#key是接口的simpleName,value是实现类的完整名称UpfileDao=cn.itcast.dao.impl.UpfileDaoImpl泛型方法public <T> T createDao(Class<T> interfaceClass)*/public class DaoFactory {   //1单例   private DaoFactory(){   };   private static final DaoFactory instance=new DaoFactory();   public static DaoFactory getInstance(){      return instance;   }   //2读配置      private static Properties pro=new Properties();   static{      InputStream in=DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");      try {         pro.load(in);      } catch (IOException e) {         // 静态代码块中异常只可抓后转型         throw new DaoException(e);      }   }   //3泛型方法(重点)   public <T> T createDao(Class<T> interfaceClass){      String key=interfaceClass.getSimpleName();      String value=pro.getProperty(key);      try {         return (T) Class.forName(value).newInstance();      } catch (Exception e) {         throw new DaoException(e);      }   }}



BusinessServiceImpl位于service.impl包

package cn.itcast.service.impl;import java.io.File;import java.util.List;import cn.itcast.dao.UpfileDao;import cn.itcast.domain.Upfile;import cn.itcast.factory.DaoFactory;import cn.itcast.service.BusinessService;import cn.itcast.utils.JdbcUtils;public class BusinessServiceImpl implements BusinessService {   //薄薄的业务层,内部维护了一个私有成员dao,   //所有功能调用dao工厂产生的dao实现类的实例完成   private UpfileDao dao=DaoFactory.getInstance().createDao(UpfileDao.class);   public void addUpfile(Upfile f){      dao.add(f);   }   public List<Upfile> getAllUpfile(){      return dao.getAll();   }   public Upfile findUpfile(String id){      return dao.find(id);   }   public void updateUpfile(Upfile f){      dao.update(f);   }   //重点是删除记录和文件!   //service业务层(通过工具类JdbcUtils)负责:开启事务,提交事务,释放连接!   //dao删除时通过JdbcUtils获取线程上绑定的连接   public void deleteUpfile(String id){      //1,开启事务      JdbcUtils.startTransaction();      //2,删除记录      dao.delete(id);      //int i=1/0;      //3,删除文件      Upfile f=dao.find(id);      File file=new File(f.getSavepath()+File.separator+f.getUuidname());      if(file.exists()){         file.delete();      }      //4,全部删除时,才提交事务      JdbcUtils.commitTransaction();      //5,千万记得释放连接和从ThreadLocal中移除连接      JdbcUtils.freeConnection();   }}



BusinessService位于service包

package cn.itcast.service;import java.util.List;import cn.itcast.domain.Upfile;public interface BusinessService {   public abstract void addUpfile(Upfile f);   public abstract List<Upfile> getAllUpfile();   public abstract Upfile findUpfile(String id);   public abstract void updateUpfile(Upfile f);   public abstract void deleteUpfile(String id);}



DaoException位于exception包

package cn.itcast.exception;public class DaoException extends RuntimeException {public DaoException() {super();   }   public DaoException(String message, Throwable cause) {      super(message, cause);   }   public DaoException(String message) {      super(message);   }   public DaoException(Throwable cause) {      super(cause);   }}



NoFileWebException位于exception包


package cn.itcast.exception;import java.io.PrintStream;import java.io.PrintWriter;public class NoFileWebException extends Exception {   public NoFileWebException() {      super();   }   public NoFileWebException(String message, Throwable cause) {      super(message, cause);   }   public NoFileWebException(String message) {      super(message);   }   public NoFileWebException(Throwable cause) {      super(cause);   }}


UnSupportedFileWebException位于exception包

package cn.itcast.exception;public class UnSupportedFileWebException extends Exception {   public UnSupportedFileWebException() {      super();   }   public UnSupportedFileWebException(String message, Throwable cause) {      super(message, cause);   }   public UnSupportedFileWebException(String message) {      super(message);   }   public UnSupportedFileWebException(Throwable cause) {      super(cause);   }}



WebUtils位于utils

package cn.itcast.utils;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.lang.reflect.InvocationTargetException;import java.util.Arrays;import java.util.Date;import java.util.List;import java.util.UUID;import javax.servlet.http.HttpServletRequest;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadBase;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;import cn.itcast.domain.Upfile;import cn.itcast.exception.NoFileWebException;import cn.itcast.exception.UnSupportedFileWebException;/*WebUtils将是整个案例的重点!首先是简单步骤,处理上传文件数据第1步,首先new 一个未经过配置的工厂实例DiskFileItemFactory第2步,用提供的工厂创建一个解析上传文件的解析器实例ServletFileUpload!!第3步,用解析器的parseRequest方法,解析request中提交的数据         每个表单项都封装成一个FileItem对象,加入list集合!第4步,迭代list集合第5步,isFormField判断普通字段还是上传字段         如果是上传字段getInputStream,一顿狂写下面是详细地处理上传文件过程~注意各类细节问题~*/public class WebUtils {   //参数中父路径诸如:\\WEB-INF\\upload   public static Upfile doUpload(HttpServletRequest request, String parentPath) throws UnSupportedFileWebException,FileUploadException, UnsupportedEncodingException, IllegalAccessException, InvocationTargetException, NoFileWebException{      Upfile bean=new Upfile();      try{      List<String> types=Arrays.asList("jpg","bmp","gif","png","txt","avi","pdf","mkv","mp3");         DiskFileItemFactory factory=new DiskFileItemFactory();         //重点一句,获取并创建临时目录         String tempStr=request.getSession().getServletContext().getRealPath("/WEB-INF/temp");         File temp=new File(tempStr);         if (!temp.exists()) {            temp.mkdirs();         }         ServletFileUpload upload=new ServletFileUpload(factory);         //设置允许上传的文件大小,FileSizeLimitExceededException         //如果超过会抛异常,工具类必须抓住,原样转抛         upload.setFileSizeMax(1024*1024*50);         //细节:在解析request之前,必须先解决上传文件名的中文乱码问题         upload.setHeaderEncoding("UTF-8");         List<FileItem> list=upload.parseRequest(request);         for (FileItem item : list) {            if (item.isFormField()) {               //username=aaa  description=bbb               String fieldName=item.getFieldName();               //或者手动转fieldValue=new String(fieldValue.getBytes("iso8859-1"),"utf-8");               String fieldValue=item.getString("utf-8");               //将表单的值封装到bean里面去,需要提前准备好一个Bean               //已封装好2个:username,description,               BeanUtils.setProperty(bean, fieldName, fieldValue);            } else {               //如果表单项是file,用个流关联,狂读写               //1,getName先得到上传文件原始名filename称形如a.txt               //注意getName是针对上传文件,取其文件名的               // item.getName() 如果是IE6     C:\Documents and Settings\Admin\桌面\a.txt                // item.getName() 如果是IE7     a.txt               //得到上传文件名(向下兼容IE6)A.TXT(这个数据库中专门有一个列存原始名称)               String filename=item.getName();               filename=filename.substring(filename.lastIndexOf("\\")+1);               if (filename==null || "".equals(filename.trim())) {                  //如果文件名是空的,抛异常给service                  throw new NoFileWebException();               }               //1.1,判断后缀是否允许!               String ext=filename.substring(filename.lastIndexOf(".")+1);               if(!types.contains(ext)){                  throw new UnSupportedFileWebException();               }               //2,用UUID算法,生成uuidname(不含原始文件名,只取其后缀)如X-X-X-X.txt               //得到文件的保存名称X-X-X.TXT               String uuidname=generateUUIDName(filename);               //3,根据uuidname的哈希值(如X-X-X-X.txt)和父路径,               //生成savepath:C:\\...\\day18_upload\\WEB-INF\\upload\\15\\4               //得到文件的保存路径\\upload\\4\\3               String savepath=generateSavePath(parentPath,uuidname);               //4,根据savepath和uuidname组成目的地,一顿狂读写               InputStream in = null;               OutputStream out = null;               try {                  in=item.getInputStream();               //   \\upload\\4\\3X-X-X.TXT                  out=new FileOutputStream(savepath+File.separator+uuidname);                  byte[] buf = new byte[1024];                  int len = 0;                  while ((len = in.read(buf)) != -1) {                     out.write(buf, 0, len);                  }               } catch (IOException e) {                  e.printStackTrace();               } finally {                  if (in != null) {                     try {                        in.close();                     } catch (IOException e) {                        throw new RuntimeException("in关闭失败!");                     }                     in = null;                  }                  if (out != null) {                     try {                        out.close();                     } catch (IOException e) {                        throw new RuntimeException("out关闭失败!");                     }                     out = null;                  }                  //删除临时文件:在程序中处理完上传文件后,                  //一定要记得调用item.delete()方法,以删除临时文件                  //必须是在关闭流之后,finally代码块中,确保删除成功!                  item.delete();  //虽然有时会自动删除临时文件               }               //将文件写入磁盘之后,封装所有信息,返回bean               //前面普通表单已经封装两列:username,description               //ID,考虑 到与其他表合并,所有用唯一ID               bean.setId(UUID.randomUUID().toString());               // x-x-x.txt               bean.setUuidname(uuidname);//X-X-X-X.txt               //A.TXT(这个数据库中专门有一个列存原始名称)               bean.setFilename(filename);//a.txt            //  /upload/4/3               bean.setSavepath(savepath);//C:\\...\\day18_upload\\WEB-INF\\upload\\15\\4               bean.setUptime(new Date());            }         }      }catch(FileSizeLimitExceededException e){         throw e;      }      return bean;   }   private static String generateSavePath(String parentPath, String uuidname) {      //根据uuidname的哈希值(如X-X-X-X.txt)和父路径,      //生成savepath:C:\\...\\day18_upload\\WEB-INF\\upload\\15\\4      //别忘记健壮性判断      int hashCode=uuidname.hashCode();      int dir1=hashCode&15;      int dir2=(hashCode>>4)&15;      String savepath=parentPath+File.separator+dir1+File.separator+dir2;      File file=new File(savepath);      if (!file.exists()) {         file.mkdirs();      }      return savepath;   }   private static String generateUUIDName(String filename) {      //用UUID算法,生成uuidname(不含原始文件名,只取其后缀)如X-X-X-X.txt      //因为专门有一列存UUID名,还有一列专门存原始文件名,a.txt      //所以不需要原始文件名,只需要加后缀      String ext=filename.substring(filename.lastIndexOf("."));      return UUID.randomUUID().toString()+ext;   }}


UpfileServlet位于web.controller包

package cn.itcast.web.controller;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileUploadBase;import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;import org.apache.commons.fileupload.servlet.ServletFileUpload;import cn.itcast.domain.Upfile;import cn.itcast.exception.NoFileWebException;import cn.itcast.exception.UnSupportedFileWebException;import cn.itcast.service.BusinessService;import cn.itcast.service.impl.BusinessServiceImpl;import cn.itcast.utils.WebUtils;public class UpfileServlet extends HttpServlet {//doGet处理首页发来的上传文件请求,生成一个表单页面,给用户上传//doGet处理生成显示上传页面,并跳转到jsp,public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.getRequestDispatcher("/WEB-INF/jsp/addfile.jsp").forward(request, response);return;}//正式处理上传的Post请求//doPost处理上传表单页面发来的Post文件上传,并告诉用户是否上传成功public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//这儿将是整个案例的重点!//首先判断是不是文件上传,以防万一if (!ServletFileUpload.isMultipartContent(request)) {request.setAttribute("message", "非法提交");request.getRequestDispatcher("/message.jsp").forward(request, response);return;}try {//如果是文件上传,简化书写,//使用一个WebUtils工具类完成处理文件上传相关细节String parentPath=this.getServletContext().getRealPath("/WEB-INF/upload");//工具处理后,返回一个封将好的Upfile对象(只允许单文件上传)Upfile f=WebUtils.doUpload(request,parentPath);//此处应该对f进行有效性校验~//调用业务层:添加文件信息到数据库BusinessService service=new BusinessServiceImpl();service.addUpfile(f);request.setAttribute("message", "文件上传成功");}catch (NoFileWebException e) {//明显知道是什么异常了,不需要记录request.setAttribute("message", "不允许上传空文件");request.getRequestDispatcher("/message.jsp").forward(request, response);return;}catch (UnSupportedFileWebException e) {//明显知道是什么异常了,不需要记录request.setAttribute("message", "不支持的文件类型");} catch (FileSizeLimitExceededException e) {//明显知道是什么异常了,不需要记录request.setAttribute("message", "文件不能超过50M");} catch (Exception e) {e.printStackTrace();request.setAttribute("message", "文件上传失败");}//无论上传成功或是失败都跳至全局消息显示页面request.getRequestDispatcher("/message.jsp").forward(request, response);}}



ListAllfilesServlet位于web.controller包

package cn.itcast.web.controller;import java.io.IOException;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.itcast.domain.Upfile;import cn.itcast.service.BusinessService;import cn.itcast.service.impl.BusinessServiceImpl;public class ListAllfilesServlet extends HttpServlet {//处理首页发来的GET请求,生成JSP页面,public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {BusinessService service=new BusinessServiceImpl();List<Upfile>  list=service.getAllUpfile();request.setAttribute("list", list);request.getRequestDispatcher("/WEB-INF/jsp/listfiles.jsp").forward(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}



DownLoadFileServlet位于web.controller包


package cn.itcast.web.controller;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URLEncoder;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.itcast.domain.Upfile;import cn.itcast.service.BusinessService;import cn.itcast.service.impl.BusinessServiceImpl;public class DownLoadFileServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String id=request.getParameter("id");BusinessService service=new BusinessServiceImpl();Upfile f=service.findUpfile(id);//首先健壮性判断File file=new File(f.getSavepath()+File.separator+f.getUuidname());if (!file.exists()) {//存跳返request.setAttribute("message", "对不起您访问的资源已被删除~");request.getRequestDispatcher("/message.jsp").forward(request, response);return;}//文件若存在,设置response头,解决文件名的乱码问题response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(f.getFilename(),"utf-8"));//这时,才read_bInputStream in = null;OutputStream out = null;try {in=new FileInputStream(file);out=response.getOutputStream();byte[] buf = new byte[1024];int len = 0;while ((len = in.read(buf)) != -1) {out.write(buf, 0, len);}} catch (IOException e) {e.printStackTrace();} finally {if (in != null) {try {in.close();} catch (IOException e) {throw new RuntimeException("in关闭失败!");}in = null;}if (out != null) {try {out.close();} catch (IOException e) {throw new RuntimeException("out关闭失败!");}out = null;}}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}


DeleteFileServlet位于web.controller包

package cn.itcast.web.controller;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.itcast.service.BusinessService;import cn.itcast.service.impl.BusinessServiceImpl;public class DeleteFileServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try {//必须事务处理,先删除记录,后删除文件//因为若发生意外,记录可以回滚String id=request.getParameter("id");BusinessService service=new BusinessServiceImpl();//调用service层,删除记录和文件!重点是BusinessServiceImpl和JDBCUTILSservice.deleteUpfile(id);request.setAttribute("message", "删除成功");request.getRequestDispatcher("/message.jsp").forward(request, response);} catch (Exception e) {//出现异常不要紧,记录下来,并给友好提示!e.printStackTrace();request.setAttribute("message", "删除失败");request.getRequestDispatcher("/message.jsp").forward(request,response);}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}



index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";//out.write("path:"+path);//path:/day18_upload//out.write("basePath:"+basePath);//basePath:http://localhost:8080/day18_upload/ %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>day18上传下载案例首页</title>  </head>  <frameset rows="30%,*">  <frame name="head" src="${pageContext.request.contextPath}/head.jsp">  <frame name="main" src="#">  </frameset></html>



head.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>        <title>head</title>  </head>    <body>    <a href="${pageContext.request.contextPath }/servlet/UpfileServlet" target="main">上传文件</a>    <a  href="${pageContext.request.contextPath }/servlet/ListAllfilesServlet" target="main">列出所有文件</a>  </body></html>



addfile.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>添加上传文件页面</title>  </head>  <body style="text-align:center;"><form action="${pageContext.request.contextPath }/servlet/UpfileServlet" method="post" enctype="multipart/form-data"><table width="40%" frame="border"><tr><td>上传用户</td><td><input type="text" name="username"></td></tr><tr><td>文件</td><td><input type="file" name="file_XXX"></td></tr><tr><td>描述信息</td><td><textarea cols="30" rows="5" name="description"></textarea></td></tr><tr><td>点击开始上传</td><td><input type="submit" value="开始上传"></td></tr></table></form>      </body></html>



listfiles.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>foreach迭代生成文件列表</title>  </head>  <body style="text-align: center;">  <table width="90%" frame="border">  <tr>  <td>文件名</td>  <td>上传者</td>  <td>文件描述</td>  <td>上传时间</td>  <td>操作</td>  </tr>  <c:forEach var="f" items="${list}">  <tr>  <td>${f.filename }</td>  <td>${f.username }</td>  <td>${f.description }</td>  <td>${f.uptime }</td>  <td>  <a href="${pageContext.request.contextPath }/servlet/DownLoadFileServlet?id=${f.id }">下载</a>  <a href="${pageContext.request.contextPath }/servlet/DeleteFileServlet?id=${f.id }">删除</a>  <a href="${pageContext.request.contextPath }/servlet/UpdateFileServlet">修改</a>  </td>  </tr>  </c:forEach>  </table>  </body></html>



1 0