一、文件上传:
1、关于上传的表单的规定
<!--1 必须是post提交
2 表单的编码类型必须指定为 enctype="multipart/form-data" -->
<form action="/upload?cmd=upload" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br/>
图像:<input type="file" name="file"><br/>
<input type="submit" value="提交">
</form>
2. 在服务器端的servlet中就不能够通过request.getParameter("xxx")得到具体的值了
3、要导入包org.apache.commons.fileupload
4、文件上传相关代码
public class UploadServlet extends HttpServlet {
//设置可上传文件的后缀名
private String[] fileExts = {"doc","zip","rar","jpg","txt"};
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//检查该请求是否是一个上传表单( 必须是 post请求,和enctype="multipart/form-data")
Boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if(isMultipart){
//创建一个临时文件存放要上传的文件,第一个参数为上传文件大小,第二个参数为存放的临时目录
DiskFileItemFactory factory = new DiskFileItemFactory(1024*1024*5,new File("C:\\temp1"));
// 创建一个文件上传的句柄
ServletFileUpload upload = new ServletFileUpload(factory);
//设置上传文件的整个大小和上传的单个文件大小
upload.setSizeMax(1024*1024*50);
upload.setFileSizeMax(1024*1024*5);
try {
//把页面表单中的每一个表单元素解析成一个FileItem
List<FileItem> items = upload.parseRequest(request);
for (FileItem fileItem : items) {
//如果是一个普通的表单元素(type不是file的表单元素)
if(fileItem.isFormField()){
System.out.println(fileItem.getFieldName()); //得到对应表单元素的名字
System.out.println(fileItem.getString()); //得到表单元素的值
}else{
//获取文件的后缀名
String fileName = fileItem.getName();//得到文件的名字
String fileExt = fileName.substring(fileName.lastIndexOf(".")+1, fileName.length());
if(Arrays.binarySearch(fileExts, fileExt)!=-1){
try {
//将文件上传到项目的upload目录并命名,getRealPath可以得到该web项目下包含/upload的绝对路径
fileItem.write(new File(getServletContext().getRealPath("/upload")+"/"
+UUID.randomUUID().toString()+"."+fileExt));
} catch (Exception e) {
e.printStackTrace();
}
}else{
System.out.println("该文件类型不能够上传");
}
}
}
} catch (SizeLimitExceededException e) {
System.out.println("整个请求的大小超过了规定的大小...");
} catch (FileSizeLimitExceededException e) {
System.out.println("请求中一个上传文件的大小超过了规定的大小...");
}catch (FileUploadException e) {
e.printStackTrace();
}
}
}
}
5、文件上传的实例employee表单
第一步:创建employee的domain类,包含所需数据域。注意在其中定义文件上传的相对路径url
创建与其数据域对应的数据库表单employee,引入.properties配置文件链接数据库
第二步:创建Util类DataSourceUtil.java来加载配置文件
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DataSourceUtil {
private static DataSource dataSource;
static{
try {
Properties properties = new Properties();
//加载配置文件
properties.load(DataSourceUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
//创建dataSource
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSouce(){
return dataSource;
}
}
第三步:创建DAO类,接口IEmployeeDAO定义增删改查的操作,EmployeeDAOImpl实现这个接口进行具体操作处理
public class EmployeeDAOImpl implements IEmployeeDAO {
private QueryRunner queryRunner = null;
public EmployeeDAOImpl() {
queryRunner = new QueryRunner(DataSourceUtil.getDataSouce());
}
@Override
public void save(Employee employee) {
//1. 创建连接
//2. 根据sql的模板创建preparedStatement
//3. 向preparedStatement设置参数
//4. 执行sql
//5. 关闭资源
String sql = "insert into employee values(null,?,?,?,?,?)";
Object[] params = {employee.getName(),employee.getSex(),employee.getTel(),employee.getFileName(),employee.getUrl()
};
execute(sql, params);
}
@Override
public void remove(Long id) {
String sql = "delete from employee where id = ?";
Object[] params = {id};
execute(sql, params);
}
@Override
public void update(Long id, Employee employee) {
String sql = "update employee set name=?,sex=?,tel=?,fileName=?,url=? where id=?";
Object[] params = {employee.getName(),employee.getSex(),employee.getTel(),employee.getFileName(),employee.getUrl()
,id};
execute(sql, params);
}
public void execute(String sql,Object...params){
try { //upadate方法用于sql的insert,delete,update
queryRunner.update(sql, params);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public Employee get(Long id) {
try {
// new BeanHandler<Employee>(Employee.class)
// new BeanHanlder中传入的泛型参数是指: query方法返回的类型
// new BeanHandler<Employee>(Employee.class) 构造函数中传入的类型是将sql语句执行的结果转换为什么类型的对象
//前提: sql查询出来的结果的列名要和employee类的属性名字对应
return queryRunner.query("select * from employee where id=?", new BeanHandler<Employee>(Employee.class), id);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Employee> list() {
try {
// 前提: sql查询出来的结果的列名要和employee类的属性名字对应,query方法用于sql的select;返回的是一个Employee对象的List
return queryRunner.query("select * from employee", new BeanListHandler<Employee>(Employee.class));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
第四步:创建servlet类EmployeeServlet,save方法先设置employee对象的属性值,再把属性值用DAO操作的save方法保存到数据库中。
其中HttpServletRequestWithUpload类是抽取出来的文件上传下载的util类,CFile是一个domain
public class HttpServletRequestWithUpload extends HttpServletRequestWrapper {
private Map<String, String> textMap = new HashMap<String, String>();
private Map<String, FileItem> fileMap = new HashMap<String, FileItem>();
private Boolean isMultipart;
public HttpServletRequestWithUpload(HttpServletRequest request) {
super(request);
isMultipart = ServletFileUpload.isMultipartContent(request);
if(isMultipart){
FileItemFactory fileItemFactory = new DiskFileItemFactory(1024*1024*5, new File("C:/temp1"));
ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
//设置整个请求中的文件大小 , 如果超出将会抛出SizeLimitExceededException
fileUpload.setSizeMax(1024*1024*20);
//设置单个文件的大小 //如果超出将会抛出FileSizeLimitExceededException
fileUpload.setFileSizeMax(1024*1025*5);
try {
List<FileItem> fileItems = fileUpload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if(fileItem.isFormField()){ //普通表单元素 , 通过上传表单提交过来的中文必须通过GET方式处理乱码.... 通过 request.setCharacterEncoding("UTF-8"); 是无法处理乱码的
textMap.put(fileItem.getFieldName(), new String(fileItem.getString().getBytes("ISO-8859-1"),"UTF-8"));
}else{ //上次表单元素
String AllowFileExt = getSession().getServletContext().getInitParameter("AllowFileExt");
String NotAllowFileExt = getSession().getServletContext().getInitParameter("NotAllowFileExt");
if(fileItem.getSize()!=0){
String fileExt = FilenameUtils.getExtension(fileItem.getName());
//当后缀名不合法的时候抛出异常
if(StringUtils.contains(AllowFileExt, fileExt.toLowerCase())|| !StringUtils.contains(NotAllowFileExt, fileExt)){
fileMap.put(fileItem.getFieldName(), fileItem);
}else{
throw new LogicException("不支持该类型文件");
}
}
}
}
} catch (FileSizeLimitExceededException e) {
throw new LogicException("其中的一个文件的大小超出来规定的大小");
} catch (SizeLimitExceededException e) {
throw new LogicException("上传的所有文件的总大小超出来规定的大小");
} catch (FileUploadException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
@Override
public String getParameter(String name) {
if(isMultipart){
return textMap.get(name);
}
return super.getParameter(name);
}
@Override
public Map getParameterMap() {
if(isMultipart){
return textMap;
}
return super.getParameterMap();
}
/**
* @param uploadPath 文件要上传的目录
* @param fieldName 要上传的表单元素的名字
* @return
*/
public CFile upload(String uploadPath,String fieldName){
FileItem fileItem = fileMap.get(fieldName);
if(fileItem!=null){
String fileName = FilenameUtils.getName(fileItem.getName());//得到文件的不带路径但是带后缀名的名字
String targetPath = uploadPath+"/"+UUID.randomUUID().toString()+"."+FilenameUtils.getExtension(fileName);
try {
// E:\workspace\day22\WebContent/upload/asdfasdfaia98ower.jpg
fileItem.write(new File(getSession().getServletContext().getRealPath("/")+targetPath));
} catch (Exception e) {
e.printStackTrace();
}
return new CFile(fileName,targetPath);
}
return null;
}
}
通过上传表单提交的中文必须通过get方式处理乱码
public class EmployeeServlet extends HttpServlet {
private IEmployeeDAO employeeDAO ;
@Override
public void init() throws ServletException {
employeeDAO = new EmployeeDAOImpl();
}
/*
*根据cmd找方法执行.. 默认执行list方法
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //根据反射获得url中的cmd,如果cmd为null则直接调用list方法
request.setCharacterEncoding("UTF-8");
String cmd = request.getParameter("cmd");
if(StringUtils.isNotBlank(cmd)){
try {
Method method = this.getClass().getMethod(cmd, HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this, request,response);
} catch (Exception e) {
list(request, response);
}
}else{
list(request, response);
}
}
public void save(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpServletRequestWithUpload httpServletRequestWithUpload = null;
try {
httpServletRequestWithUpload = new HttpServletRequestWithUpload(request);
} catch (LogicException e) { //如果出现了异常就让error.jsp显示错误信息...
String message = e.getMessage();
request.setAttribute("message", message);
request.getRequestDispatcher("/error.jsp").forward(request, response);
return;
}
if(httpServletRequestWithUpload!=null){
Employee employee = new Employee();
employee.setName(httpServletRequestWithUpload.getParameter("name"));
employee.setSex(httpServletRequestWithUpload.getParameter("sex"));
employee.setTel(httpServletRequestWithUpload.getParameter("tel"));
CFile cFile = httpServletRequestWithUpload.upload("/upload", "uploadFile");
if(cFile!=null){
employee.setFileName(cFile.getSrcFileName());
employee.setUrl(cFile.getTargetFilePath());
}
employeeDAO.save(employee);
response.sendRedirect("/employee?cm=list");
}
}
public void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
Employee employee = employeeDAO.get(Long.parseLong(id));
request.setAttribute("employee", employee);
request.getRequestDispatcher("/WEB-INF/view/employee/edit.jsp").forward(request, response);
}
//在修改的时候,如果说没有选择上传文件,将会保留之前的文件, 如果选择了就会把原来的从系统中删掉,上传选择的文件...
public void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpServletRequestWithUpload hru = new HttpServletRequestWithUpload(request);
String id = hru.getParameter("id");
Employee employee = employeeDAO.get(Long.parseLong(id));
employee.setName(hru.getParameter("name"));
employee.setSex(hru.getParameter("sex"));
employee.setTel(hru.getParameter("tel"));
CFile cFile = hru.upload("/upload", "uploadFile");
//说明选择了文件
if(cFile!=null){
String srcUrl = employee.getUrl();
deleteFile(srcUrl);
employee.setUrl(cFile.getTargetFilePath());
employee.setFileName(cFile.getSrcFileName());
}
employeeDAO.update(Long.parseLong(id), employee);
response.sendRedirect("/employee?cmd=list");
}
/**
* 删除一个文件
* @param srcUrl 相对路径
*/
public void deleteFile(String srcUrl) {
File file = new File(getServletContext().getRealPath("/")+srcUrl);
if(file.exists()){
file.delete();
}
}
public void remove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
//删除的时候可不能够单单删除数据库中的记录,也要删除该记录对应的文件
Employee employee = employeeDAO.get(Long.parseLong(id));
String url = employee.getUrl(); //仅仅是相对路径
employeeDAO.remove(Long.parseLong(id));
deleteFile(url);
response.sendRedirect("/employee?cm=list");
}
public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Employee> employees = employeeDAO.list();
request.setAttribute("employees", employees);
request.getRequestDispatcher("/WEB-INF/view/employee/list.jsp").forward(request, response);
}
public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/view/employee/edit.jsp").forward(request, response);
}
}
二、文件下载:
需要设置相应的ContentType为application/x-msdownload
需要根据不同浏览器设置不同的Header的Content-Disposition项
public class DownloadServlet extends HttpServlet {
private IEmployeeDAO employeeDAO;
@Override
public void init() throws ServletException {
employeeDAO = new EmployeeDAOImpl();
}
/*
通过Servlet去读取文件,然后在写到响应的输出流中....
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/x-msdownload");
String id = request.getParameter("id");
Employee employee = employeeDAO.get(Long.parseLong(id));
String user_agent = request.getHeader("User-Agent");
if(user_agent.contains("IE")){
response.setHeader("Content-Disposition", "attachment; filename="+URLEncoder.encode(employee.getFileName(), "UTF-8"));
}else if(user_agent.contains("Firefox")){
response.setHeader("Content-Disposition", "attachment; filename="+new String(employee.getFileName().getBytes("UTF-8"),"ISO-8859-1"));
}
/*
* 权限的判断
*
*/
File file = new File(getServletContext().getRealPath("/")+employee.getUrl());
if(file.exists()){
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[1024*5];
int num;
OutputStream outputStream = response.getOutputStream(); //得到响应的输出流...
while((num=bufferedInputStream.read(b))!=-1){
outputStream.write(b, 0, num);
outputStream.flush();
}
}
}
}