文件上传与下载
项目包 (不喜勿喷)
链接:https://pan.baidu.com/s/1sCSFE3kcLFNin04rZTl46Q
提取码:0000
复制这段内容后打开百度网盘手机App,操作更方便哦
上传
- 概念:
- 当用户在前端页面点击文件上传后,文件数据提交给服务器端,实现保存
- 步骤:
- 注意:
- 文件上传表单提交方式:post
- 表单提交类型:multipart/form-data
页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
<input type="text" name="username" placeholder="请输入用户名"/><br/>
<input type="file" name="photo1"><br/>
<input type="file" name="photo1"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
核心服务器程序
- 核心步骤
- 编写Servlet
- 使用@MultipartConfig进行注解
- 使用javax.servlet.http.Part接口接收文件类型
Part file = request.getPart("file");
文件上传细节
- 安全问题
- 上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下
- 文件覆盖
- 散列存储
- 文件类型限制
实践代码
servlet
@WebServlet(name = "UploadServlet",value = "/upload")
@MultipartConfig(maxFileSize = 1024*1024*5,maxRequestSize = 1024*1024*20)
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Collection<Part> parts = request.getParts();
String basePath = this.getServletContext().getRealPath("WEB-INF/upload");
File dir = new File(basePath);
if (!dir.exists()){
dir.mkdirs();
}
PrintWriter out = response.getWriter();
List<String> allowExts = new ArrayList<>();
allowExts.add("jpg");
allowExts.add("png");
allowExts.add("bmp");
if (parts!=null){
for (Part part : parts) {
String submittedFileName = part.getSubmittedFileName();
if (submittedFileName==null){
String name = part.getName();
String value = request.getParameter(name);
System.out.println(name+"....."+value);
}else{
String dis = part.getHeader("Content-Disposition");
String filename = dis.substring(dis.lastIndexOf("filename=") + 10, dis.length() - 1);
filename = filename.substring(filename.lastIndexOf("\\") + 1);
if(filename.equals("")){
out.write("没有选择文件<br/>");
continue;
}
String ext = filename.substring(filename.lastIndexOf(".") + 1);
if (!allowExts.contains(ext)){
out.write("文件格式不匹配<br/>");
continue;
}
String newFileName = UploadUtils.newFileName(filename);
String newPath = UploadUtils.makePath(basePath, filename);
part.write(newPath+File.separator+"/"+newFileName);
part.delete();
out.write(filename+"上传成功<br/>");
}
}
}
}
工具类
public static String newFileName(String oldFileName){
UUID uuid = UUID.randomUUID();
return uuid.toString().replace("-", "")+"_"+oldFileName;
}
public static String makePath(String basePath,String oldFileName){
int hashCode = oldFileName.hashCode();
int dir1 = hashCode&0xf;
int dir2 = (hashCode>>4)&0xf;
String path = basePath+ File.separator+dir1+File.separator+dir2;
File dir = new File(path);
if (!dir.exists()){
dir.mkdirs();
}
return path;
}
public static void listDir(File dir, HashMap<String,String> hashMap){
File[] files = dir.listFiles();
if (files!=null){
for (File file : files) {
if (file.isDirectory()){
listDir(file, hashMap);
}else {
String uuidFileName = file.getName();
String fileName = uuidFileName.substring(uuidFileName.indexOf("_") + 1);
hashMap.put(uuidFileName, fileName);
}
}
}
}
下载
文件下载
- 概念:
- 首先我们要有一个页面列出上传文目录下的无所有文件
- 当用户点击文件下载超链接时,就进行下载操作
- 步骤
获取文件列表
@WebServlet(name = "DownListServlet",value = "/downlist")
public class DownListServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String basePath = this.getServletContext().getRealPath("WEB-INF/upload");
HashMap<String, String> hashMap = new HashMap<>();
UploadUtils.listDir(new File(basePath), hashMap);
request.setAttribute("hashmap", hashMap);
request.getRequestDispatcher("/download.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
下载文件列表
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>下载页面</title>
</head>
<body>
<%-- <form action="${pageContext.request.contextPath}/download" method="post" enctype="multipart/form-data">--%>
<h3>下载链接</h3>
<ul>
<c:forEach items="${hashmap}" var="entry">
<li>
<%-- 这样写 servlet 要进行解码 URLEncoder.encode(filename, "utf-8");--%>
<%-- <a href="${pageContext.request.contextPath}/download?filename=${entry.key}">${entry.value}</a>--%>
<%-- <c:out value="${entry.value}"></c:out>--%>
<%-- 将<c:url>标签将URL格式化为一个字符串,然后存储在一个变量中。
这个标签在需要的时候会自动重写URL。 可以免去解码--%>
<c:url var="myurl" value="/download">
<c:param name="filename" value="${entry.key}"></c:param>
</c:url>
<a href="${myurl}">${entry.value}</a>
</li>
</c:forEach>
</ul>
<%-- </form>--%>
</body>
</html>
下载处理
- 获取客户端需要下载的文件名,使用流读取后,并返回给浏览器
- 注意
- 添加响应头:content-disposition,浏览器保存文件 (不加的话,只是在浏览器显示,不会下载到本地硬盘)
- 中文文件名需要编码
@WebServlet(name = "DownloadServlet",value = "/download")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String uuidFileName = request.getParameter("filename");
System.out.println(uuidFileName);
String filename = uuidFileName.substring(uuidFileName.indexOf("_") + 1);
String basePath = this.getServletContext().getRealPath("WEB-INF/upload");
String path = UploadUtils.makePath(basePath, filename);
FileInputStream fis = new FileInputStream(path+ File.separator+uuidFileName);
ServletOutputStream os = response.getOutputStream();
byte[] buffer = new byte[1024*4];
int len;
response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(filename, "utf-8"));
while ((len=fis.read(buffer))!=-1){
os.write(buffer, 0, len);
}
}
项目实践部分代码(添加书籍)
servlet
@WebServlet(name = "AddBookServlet",value = "/addBook")
@MultipartConfig(maxFileSize = 1024*1024*4,maxRequestSize = 1024*1024*20)
public class AddBookServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
if (request.getSession().getAttribute("username")==null){
request.setAttribute("msg", "请先登录");
request.getRequestDispatcher("/login.html").forward(request, response);
return;
}
BookService bookService = new BookServiceImpl();
String title = request.getParameter("title");
String author = request.getParameter("author");
String publicDate = request.getParameter("publicDate");
String publisher = request.getParameter("publisher");
String isbn = request.getParameter("isbn");
String price = request.getParameter("price");
String cid = request.getParameter("cid");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
Part picture = request.getPart("picture");
String basePath = this.getServletContext().getRealPath("WEB-INF/bookCovers");
File dir = new File(basePath);
if (!dir.exists()){
dir.mkdirs();
}
String newFileName = null;
if (!picture.equals("")){
String dis = picture.getHeader("Content-Disposition");
String filename = dis.substring(dis.lastIndexOf("filename=") + 10, dis.length() - 1);
filename = filename.substring(filename.lastIndexOf("\\") + 1);
String ext = filename.substring(filename.lastIndexOf(".") + 1);
UUID uuid = UUID.randomUUID();
String uu = uuid.toString().replace("-", "");
newFileName = uu+"."+ext;
picture.write(basePath+File.separator+newFileName);
picture.delete();
}
try {
Book book = new Book(0, title, author, sf.parse(publicDate), publisher, isbn, new BigDecimal(price), newFileName, Integer.parseInt(cid));
boolean flag = bookService.addBook(book);
if (!flag){
request.setAttribute("msg", "添加失败");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
response.sendRedirect(request.getContextPath()+"/pagequery");
}catch (Exception e){
request.setAttribute("msg", e);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
jsp
<form action="${pageContext.request.contextPath}/addBook" method="post" enctype="multipart/form-data">
<h3>添加书籍</h3>
<table>
<tr>
<td>书名</td>
<td>
<input type="text" name="title">
</td>
</tr>
<tr>
<td>作者</td>
<td>
<input type="text" name="author">
</td>
</tr>
<tr>
<td>出版日期</td>
<td>
<input type="date" name="publicDate">
</td>
</tr>
<tr>
<td>出版社</td>
<td>
<input type="text" name="publisher">
</td>
</tr>
<tr>
<td>isbn</td>
<td>
<input type="text" name="isbn">
</td>
</tr>
<tr>
<td>价格</td>
<td>
<input type="text" name="price">
</td>
</tr>
<%-- <tr>
<td>图片</td>
<td>
<input type="text" name="picture">
</td>
</tr>--%>
<tr>
<td>图片</td>
<td>
<input type="file" name="picture">
</td>
</tr>
<tr>
<td>类别</td>
<td>
<input type="text" name="cid">
</td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>
<td>
<input type="file" name="picture">
</td>
</tr>
<tr>
<td>类别</td>
<td>
<input type="text" name="cid">
</td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
```