使用 fileupload 组件完成文件的上传应用
1. 使用 fileupload 组件完成文件的上传应用
commons-dbutils-1.3.jar
commons-fileupload-1.2.1.jar
1). 需求:
> 在 upload.jsp 页面上使用 jQuery 实现 "新增一个附件", "删除附件". 但至少需要保留一个.
> 对文件的扩展名和文件的大小进行验证. 以下的规则是可配置的. 而不是写死在程序中的.
①文件的扩展名必须为 .pptx, docx, doc
② 每个文件的大小不能超过 1 M
③ 总的文件大小不能超过 5 M.
upload.properties
exts=pptx,docx,doc
file.max.size=1048576
total.file.max.size=5242880
> 若验证失败, 则在 upload.jsp 页面上显示错误消息:
① 若某一个文件不符合要求: xxx 文件扩展名不合法 或 xxx 文件大小超过 1 M
② 总的文件大小不能超过 5 M.
> 若验证通过, 则进行文件的上传操作
① 文件上传, 并给一个不能和其他文件重复的名字, 但扩展名不变
② 在对应的数据表中添加一条记录.
id file_name file_path file_desc
FileUploadServlet.java
package com.aff.fileupload.app.servlet; 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.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;mport com.aff.fileupload.app.bean.FileUploadBean;
import com.aff.fileupload.app.db.UploadFileDao;
import com.aff.fileupload.app.exception.InvalidExtNameException;
import com.aff.fileupload.app.utils.FileUploadAppProperties;
import com.aff.fileupload.app.utils.FileUtils; @WebServlet("/app/fileuploadservlet")
public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String FILE_PATH = "/WEB-INF/files/"; private static final String TEMP_DIR = "d:\\tempDirectory"; private UploadFileDao dao = new UploadFileDao(); protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String path = null; // 获取 ServletFileUpload 对象.
ServletFileUpload upload = getServletFileUpload(); try { // 把需要上传的 FileItem 都放入到该 Map 中
// 键: 文件的待存放的路径, 值: 对应的 FileItem 对象
Map<String, FileItem> uploadFiles = new HashMap<String, FileItem>(); // 解析请求, 得到 FileItem 的集合.
List<FileItem> items = upload.parseRequest(request); // 1. 构建 FileUploadBean 的集合, 同时填充 uploadFiles
List<FileUploadBean> beans = buildFileUploadBeans(items, uploadFiles); // 2. 校验扩展名:
vaidateExtName(beans); // 3. 校验文件的大小: 在解析时, 已经校验了, 我们只需要通过异常得到结果. // 4. 进行文件的上传操作.
upload(uploadFiles); // 5. 把上传的信息保存到数据库中
saveBeans(beans); // 6. 删除临时文件夹的临时文件
FileUtils.delAllFile(TEMP_DIR); path = "/app/success.jsp"; } catch (Exception e) {
e.printStackTrace();
path = "/app/upload.jsp";
request.setAttribute("message", e.getMessage());
} request.getRequestDispatcher(path).forward(request, response);
} private void saveBeans(List<FileUploadBean> beans) {
dao.save(beans);
} /**
* 文件上传前的准备工作. 得到 filePath 和 InputStream
*
* @param uploadFiles
* @throws IOException
*/
private void upload(Map<String, FileItem> uploadFiles) throws IOException {
for (Map.Entry<String, FileItem> uploadFile : uploadFiles.entrySet()) {
String filePath = uploadFile.getKey();
FileItem item = uploadFile.getValue(); upload(filePath, item.getInputStream());
}
} /**
* 文件上传的 IO 方法.
*
* @param filePath
* @param inputStream
* @throws IOException
*/
private void upload(String filePath, InputStream inputStream) throws IOException {
OutputStream out = new FileOutputStream(filePath); byte[] buffer = new byte[1024];
int len = 0; while ((len = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, len);
} inputStream.close();
out.close(); System.out.println(filePath);
} /**
* 校验扩展名是否合法
*
* @param beans:
*/
private void vaidateExtName(List<FileUploadBean> beans) {
String exts = FileUploadAppProperties.getInstance().getProperty("exts");
List<String> extList = Arrays.asList(exts.split(","));
System.out.println(extList); for (FileUploadBean bean : beans) {
String fileName = bean.getFileName();
System.out.println(fileName.indexOf(".")); String extName = fileName.substring(fileName.lastIndexOf(".") + 1);
System.out.println(extName); if (!extList.contains(extName)) {
throw new InvalidExtNameException(fileName + "文件的扩展名不合法");
}
}
} /**
* 利用传入的 FileItem 的集合, 构建 FileUploadBean 的集合, 同时填充 uploadFiles
*
* FileUploadBean 对象封装了: id, fileName, filePath, fileDesc uploadFiles:
* Map<String, FileItem> 类型, 存放文件域类型的 FileItem. 键: 待保存的文件的名字 ,值: FileItem 对象
*
* 构建过程: 1. 对传入 FileItem 的集合进行遍历. 得到 desc 的那个 Map. 键: desc 的
* fieldName(desc1, desc2 ...). 值: desc 的那个输入的文本值
*
* 2. 对传入 FileItem 的集合进行遍历. 得到文件域的那些 FileItem 对象, 构建对应的 key (desc1 ....)
* 来获取其 desc. 构建的 FileUploadBean 对象, 并填充 beans 和 uploadFiles
*
* @param items
* @param uploadFiles
* @return
* @throws UnsupportedEncodingException
*/
private List<FileUploadBean> buildFileUploadBeans(List<FileItem> items, Map<String, FileItem> uploadFiles)
throws UnsupportedEncodingException {
List<FileUploadBean> beans = new ArrayList<>(); Map<String, String> descs = new HashMap<>(); for (int i = 0; i < items.size(); i++) {
FileItem item = items.get(i); if (item.isFormField()) {
// desc1 或 desc2 ...
String fieldName = item.getFieldName();
String desc = item.getString("UTF-8"); descs.put(fieldName, desc);
}
} for (int i = 0; i < items.size(); i++) {
FileItem item = items.get(i);
FileUploadBean bean = null;
if (!item.isFormField()) {
String fieldName = item.getFieldName();
String descName = "desc" + fieldName.substring(fieldName.length() - 1);
String desc = descs.get(descName); // 对应文件名
String fileName = item.getName();
String filePath = getFilePath(fileName); bean = new FileUploadBean(fileName, filePath, desc);
beans.add(bean); uploadFiles.put(bean.getFilePath(), item);
}
} return beans;
} /**
* 根据跟定的文件名构建一个随机的文件名 1. 构建的文件的文件名的扩展名和给定的文件的扩展名一致 2. 利用 ServletContext 的
* getRealPath 方法获取的绝对路径 3. 利用了 Random 和 当前的系统时间构建随机的文件的名字
*
* @param fileName
* @return
*/
private String getFilePath(String fileName) {
String extName = fileName.substring(fileName.lastIndexOf("."));
Random random = new Random(); String filePath = getServletContext().getRealPath(FILE_PATH) + "\\" + System.currentTimeMillis()
+ random.nextInt(100000) + extName;
return filePath;
} /**
* 构建 ServletFileUpload 对象 从配置文件中读取了部分属性, 用户设置约束. 该方法代码来源于文档.
*
* @return
*/
private ServletFileUpload getServletFileUpload() {
String fileMaxSize = FileUploadAppProperties.getInstance().getProperty("file.max.size");
String totalFileMaxSize = FileUploadAppProperties.getInstance().getProperty("total.file.max.size"); DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(1024 * 500);
File tempDirectory = new File(TEMP_DIR);
factory.setRepository(tempDirectory); ServletFileUpload upload = new ServletFileUpload(factory); upload.setSizeMax(Integer.parseInt(totalFileMaxSize));
upload.setFileSizeMax(Integer.parseInt(fileMaxSize)); return upload;
}
}
upload.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript"
src="${pageContext.request.contextPath }/scripts/jquery-1.12.3.js"></script>
<script type="text/javascript"> $(function(){
var i = 2;
$("#addFile").click(function(){
$(this).parent().parent().before("<tr class='file'><td>File"
+ i + ":</td><td><input type='file' name='file"
+ i + "'/></td></tr>"
+ "<tr class='desc'><td>Desc"
+ i + ":</td><td><input type='text' name='desc"
+ i + "'/><button id='delete"
+ i + "'>删除</button></td></tr>");
i++; //获取新添加的删除按钮
$("#delete" + (i-1)).click(function(){
var $tr = $(this).parent().parent();
$tr.prev("tr").remove();
$tr.remove(); //对 i 重写排序
$(".file").each(function(index){
var n = index + 1; $(this).find("td:first").text("File" + n);
$(this).find("td:last input").attr("name", "file" + n);
}); $(".desc").each(function(index){
var n = index + 1; $(this).find("td:first").text("Desc" + n);
$(this).find("td:last input").attr("name", "desc" + n);
}); i = i - 1;
}); return false;
}); }); </script> </head>
<body> <font color="red">${message }</font>
<br><br> <form action="fileuploadservlet" method="post" enctype="multipart/form-data"> <table>
<tr class="file">
<td>File1:</td>
<td><input type="file" name="file1"/></td>
</tr>
<tr class="desc">
<td>Desc1:</td>
<td><input type="text" name="desc1"/></td>
</tr> <tr>
<td><input type="submit" id="submit" value="提交"/></td>
<td><button id="addFile">新增一个附件</button></td>
</tr>
</table> </form>
</body>
</html>
FileUploadAppListener.java
package com.aff.fileupload.app.listener; import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties; import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener; import com.aff.fileupload.app.utils.FileUploadAppProperties; @WebListener
public class FileUploadAppListener implements ServletContextListener { public FileUploadAppListener() {
} public void contextInitialized(ServletContextEvent sce) {
InputStream is = getClass().getClassLoader().getResourceAsStream("upload.properties");
Properties properties = new Properties(); try {
properties.load(is); for (Map.Entry<Object, Object> prop : properties.entrySet()) {
String propertyName = (String) prop.getKey();
String propertyValue = (String) prop.getValue(); FileUploadAppProperties.getInstance().addProperty(propertyName, propertyValue); }
} catch (IOException e) {
e.printStackTrace();
}
} public void contextDestroyed(ServletContextEvent sce) {
}
}
UploadFileDao.java
package com.aff.fileupload.app.db; import java.sql.Connection;
import java.util.List; import com.aff.fileupload.app.bean.FileUploadBean; public class UploadFileDao extends DAO<FileUploadBean> { public List<FileUploadBean> getFiles() { Connection conn = null; try {
conn = JDBCUtils.getConnection();
String sql = "SELECT id, file_name fileName, file_path filePath, " + "file_desc fileDesc FROM upload_files";
return getForList(conn, sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn);
}
return null;
} public void save(List<FileUploadBean> uploadFiles) { Connection conn = null; try {
conn = JDBCUtils.getConnection();
String sql = "INSERT INTO upload_files (file_name, file_path, file_desc) VALUES " + "(?, ?, ?)";
for (FileUploadBean file : uploadFiles) {
update(conn, sql, file.getFileName(), file.getFilePath(), file.getFileDesc());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn);
}
}
}
FileUploadBean.java
package com.aff.fileupload.app.bean; public class FileUploadBean { private Integer id;
private String fileName;
private String filePath;
private String fileDesc;
public FileUploadBean() {
super();
}
public FileUploadBean(String fileName, String filePath, String fileDesc) {
super();
this.fileName = fileName;
this.filePath = filePath;
this.fileDesc = fileDesc;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getFileDesc() {
return fileDesc;
}
public void setFileDesc(String fileDesc) {
this.fileDesc = fileDesc;
}
}
目录
2. 如何修改小工具或框架的源代码 ?
1). 原则: 能不修改就不修改.
2). 修改的方法:
> 修改源代码, 替换 jar 包中对应的 class 文件.
> 在本地新建相同的包, 和类, 在这个类中修改即可.
3. 文件的下载:
DownloadServlet.java
package com.aff.download.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//I. 设置 contentType 响应头: 设置响应的类型是什么 ? 通知浏览器是个下载的文件
response.setContentType("application/x-msdownload"); String fileName = "文件下载.pptx";
//II. 设置 Content-Disposition 响应头: 通知浏览器不再有浏览器来自行处理(或打开)要下载的文件,
// 而由用户手工完成
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
//III. 具体的文件: 可以调用 response.getOutputStream 的方式, 以 IO 流的方式发送给客户端.
OutputStream out = response.getOutputStream();
String pptFileName = "C:\\Users\\lz\\Desktop\\NEW\\PPT\\MAPP.pptx"; InputStream in = new FileInputStream(pptFileName); byte[] buffer = new byte[1024];
int len = 0; while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
in.close();
}
}
download.jsp
<body>
<!-- 静态下载 -->
<a href="xyz.txt">download xyz.txt</a>
<br>
<br>
<a href="test.jsp">download test.jsp</a>
<br>
<br>
<a href="downloadServlet">DownLoad abcd.pptx</a>
</body>
使用 fileupload 组件完成文件的上传应用的更多相关文章
- 模拟文件上传(三):使用apache fileupload组件进行文件批量上传
其中涉及到的jar包 jsp显示层: <%@ page language="java" import="java.util.*" pageEncoding ...
- javaweb05 文件的上传一
2.使用fileupload组件完成文件的上传应用 1).需求: I. 上传 >在upload.jsp页面上使用jQuery实现"新增一个附件","删除附件&quo ...
- JavaWeb 之文件的上传下载
又到了每周更新博客的时候了,每看到自己发布的随笔阅读量上涨的时候就特别开心,我也会尽自己的努力提高自己的水平,总结出通俗易读的学习笔记,还望大家能多多支持!!! ------------------- ...
- 初学Java Web(7)——文件的上传和下载
文件上传 文件上传前的准备 在表单中必须有一个上传的控件 <input type="file" name="testImg"/> 因为 GET 方式 ...
- MVC文件上传04-使用客户端jQuery-File-Upload插件和服务端Backload组件实现多文件异步上传
本篇使用客户端jQuery-File-Upload插件和服务端Badkload组件实现多文件异步上传.MVC文件上传相关兄弟篇: MVC文件上传01-使用jquery异步上传并客户端验证类型和大小 ...
- 文件的上传Commons FileUpload(web基础学习笔记十六)
一.表单设置 <form action="<%=request.getContextPath()%>/jsp/admin/doAdd.jsp" enctype=& ...
- vue文件夹上传组件选哪个好?
一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输. ...
- B/S文件夹上传下载组件
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 先说下要求: PC端全平台支持,要求支持Windows,Mac,Linux 支持所 ...
- html5文件夹上传下载组件
我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...
随机推荐
- 【Layui__监听button】在form中监听按钮事件
1. 前言 在使用form表单的按钮时,点击按钮总是页面刷新,代码如下 <button class="layui-btn" lay-submit lay-filter=&qu ...
- Fiddler手机端抓包环境设置与过滤(一)
一.PC端Fiddler设置 1.安装https 证书 打开Fiddler->Tool->Fiddler Options->HTTPS tab,勾选上并Capture HTTPS C ...
- 使用django开发论坛输出调试信息时附加远程客户端IP地址!
前言 最近使用django开发了个匿名社区(哈士奇社区 4nmb.com),但是有个问题一直困扰我半天,就是如何在django调试信息上输出远程客户端的真实IP地址,在网上找了很多资料也没见人遇到过, ...
- 解决虚拟机中linux系统无法使用本机无线wifi联网的问题
VMware Workstation 在嵌入式开发中经常会遇到,但是显示大多数人使用开发环境是Win10 + 无线网卡,针对这种情况,需要配置虚拟机的上网环境使用的是NAT模式,将配置过程进行描述: ...
- 网络流 A - PIGS POJ - 1149 最大流
A - PIGS POJ - 1149 这个题目我开始感觉很难,然后去看了一份题解,写的很好 https://wenku.baidu.com/view/0ad00abec77da26925c5b01c ...
- 软件工程复习 WHUT
软件过程模型: 瀑布模型:界限分明的独立阶段,计划驱动的软件过程.规范软件开发活动 (例如:可分为分析.开发.维护三个阶段) 也称生命周期模型.线性模型,采用结构化分析.设计.编程技术 不足的地方:知 ...
- 【杂谈】Disruptor——RingBuffer问题整理(一)
纯CAS为啥比加锁要快? 同样是修改数据,一个采用加锁的方式保证原子性,一个采用CAS的方式保证原子性. 都是能够达到目的的,但是常用的锁(例如显式的Lock和隐式的synchonized),都会把获 ...
- 写了shell脚本想一键启动三台虚拟机的Zookeeper,却不知道为啥总是启动不了
首先,一键启动的shell脚本是这样的 #! /bin/bash case $1 in "start"){ for i in node01 node02 node03 do ssh ...
- .net core HttpClient 使用之掉坑解析(一)
一.前言 在我们开发当中经常需要向特定URL地址发送Http请求操作,在.net core 中对httpClient使用不当会造成灾难性的问题,这篇文章主要来分享.net core中通过IHttpCl ...
- JDBC04 PreparedStatement
PreparedStatement类 存在预编译,用占位符去填参数(参数索引从1开始算),可以防止SQL注入 try { Class.forName("com.mysql.cj.jdbc.D ...