文件上传与下载
文件上传
1. 文件上传的基本原理
2. 应用实例
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<html>
<head>
<title>文件上传与下载</title>
<style type="text/css">
input[type="submit"]{
outline: none;
border-radius: 5px;
cursor: pointer;
background-color: #31B0D5;
border: none;
width: 70px;
height: 35px;
font-size: 20px;
}
img {
border-radius: 50%;
}
form {
position: relative;
width: 200px;
height: 200px;
}
input[type="file"] {
position: absolute;
left: 0;
top: 0;
height: 200px;
opacity: 0;
cursor: pointer;
}
</style>
<script type="text/javascript">
function prev(event){
//获取展示图片的区域
var img = document.getElementById("prevView");
//获取文件对象
var file = event.files[0];
//获取文件阅读器
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(){
//给img的src设置图片url
img.setAttribute("src",this.result);
}
}
</script>
</head>
<body>
<!-- 表单的enctype 属性要设置为 multipart/form-data -->
<form action="/ajax/fileUpload" method="post" enctype="multipart/form-data">
修狗图片: <img src="/ajax/img/g1.png" alt="" width="200" height="200" id="prevView">
<input type="file" name="pic" id="" value="" onchange="prev(this)" /><br/>
图片名称: <input type="text" name="name" /><br/>
<input type="submit" value="上传" />
</form>
</body>
</html>
package com.zzti.fileupdown;
public class fileUploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("fileUploadServlet doPost()被执行");
//1. 判断是不是文件表单
if (ServletFileUpload.isMultipartContent(request)) {
System.out.println("~~OK~~");
//2.创建DiskFileItemFactory对象,用于构建一个解析上传数据的工具对象
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//3.创建一个解析上传数据的工具对象(表单提交的数据,就是input元素)
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
//解决接收道文件名中文乱码问题
servletFileUpload.setHeaderEncoding("utf-8");
//4.servletFileUpload对象可以把表单提交的数据(text/文件),将其封装到FileItem文件项中
try{
List<FileItem> list = servletFileUpload.parseRequest(request);
/**
* list= [name=g2.png, StoreLocation=C:\Users\pt_cheng\AppData\Local\Temp\xupload_cf3ef4b5_88b3_4d2d_880c_04bcdadb1a4f_00000000.tmp, size=73928 bytes, isFormField=false, FieldName=pic,
* name=null, StoreLocation=C:\Users\pt_cheng\AppData\Local\Temp\xupload_cf3ef4b5_88b3_4d2d_880c_04bcdadb1a4f_00000001.tmp, size=15 bytes, isFormField=true, FieldName=name]
*/
System.out.println("list= " + list);
//遍历,并分别处理
for (FileItem fileItem : list) {
//fileItem= name=g2.png, StoreLocation=C:\Users\pt_cheng\AppData\Local\Temp\xupload_cf3ef4b5_88b3_4d2d_880c_04bcdadb1a4f_00000000.tmp, size=73928 bytes, isFormField=false, FieldName=pic
System.out.println("fileItem= " + fileItem);
//判断是不是一个文件
if (fileItem.isFormField()) {
//若是文本(input text),就是true
String name = fileItem.getString("utf-8");
System.out.println("图片名称是= " + name);//图片名称是= 修狗图片222
}else {
//是一个文件
//获取上传的文件的名字
String fileName = fileItem.getName();
//上传的修狗图片是= g2.png
System.out.println("上传的修狗图片是= " + fileName);
//把这个上传到服务器的temp下的文件保存到你指定的目录
String filePath = "/upload/";
//获取到完整的目录
//fileRealPath= D:\Exercise items\ajax\src\main\webapp\xupload\
String fileRealPath = getServletContext().getRealPath(filePath);
System.out.println("fileRealPath= " + fileRealPath);
//创建这个要上传的目录
File fileRealPathDirectory = new File(fileRealPath + WebUtils.getYearMonthDay());
if (!fileRealPathDirectory.exists()) {
//如果目录不存在,就创建
fileRealPathDirectory.mkdirs();
}
//将文件拷贝到fileRealPathDirectory目录,构建上传文件的完整路径: 目录+文件名
fileName = UUID.randomUUID().toString() + "_" + System.currentTimeMillis() + "_" + fileName;
String fileFullPath = fileRealPathDirectory + "/" +fileName;
fileItem.write(new File(fileFullPath));
//提示信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("上传成功哦~~");
}
}
}catch (Exception e) {
e.printStackTrace();
}
}else{
System.out.println(" 不是文件表单。。。。 ");
}
}
}
3. 文件上传注意事项
- 如果将文件都上传到一个目录下,当上传文件很多时,会造成访问文件速度变慢。因此可以将文件上传到不同目录,根据年月日放到一个文件夹。比如:20220528
- 文件上传要考虑的因素很多,比如: 控制图片大小,尺寸,分片上传,防止恶意上传等。
- 文件上传功能,在项目中建议有限制的使用,一般用在头像,证明,合同,产品展示等。若不加限制,会造成服务器被大量空间占用。(B站评论,就不能上传图片,微信朋友圈一次只能发9张图片等)
- 文件上传,创建web/upload的文件夹,在Tomcat启动时,没有在out目录下创建对应的upload文件夹,原因是: Tomcat对应空目录是不会在out下创建相应的目录的。所以,只需在upload目录下,放入一个文件即可。
二. 文件下载
1. 文件下载示意图
2. 文件下载应用实例
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<html>
<head>
<title>文件下载</title>
</head>
<body>
<h1>文件下载</h1>
<a href="/ajax/fileDownload?name=g2.png">点击下载小狗图片</a><br/><br/>
<a href="/ajax/fileDownload?name=学习报告.txt">点击下载pdf/text文档</a><br/><br/>
</body>
</html>
package com.zzti.fileupdown;
public class fileDownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("fileDownloadServlet doPost()被执行");
//1. 先准备要下载的文件,在工作目录下out创建一个download文件夹,吧公共资源放入
//2. 获取到要下载的文件名字
request.setCharacterEncoding("utf-8");
String downLoadFileName = request.getParameter("name");
System.out.println("downLoadFileName= " + downLoadFileName);
//3. 给http响应, 设置响应头 Context-Type
ServletContext servletContext = request.getServletContext();
String downLoadPath = "/download/";
String downLoadFullPath = downLoadPath + downLoadFileName;
String mimeType = servletContext.getMimeType(downLoadFullPath);
System.out.println("mimeType= " + mimeType);
response.setContentType(mimeType);
//4. 给http响应, 设置响应头 Context-Disposition
//如果是火狐浏览器, 则中文编码需要base64
if (request.getHeader("User-Agent").contains("Firefox")) {
response.setHeader("Context-Disposition","attachment;filename==?UTF-8?B?"
+ new BASE64Encoder().encode(downLoadFileName.getBytes("UTF-8")) + "?=");
}else{
//其他主流浏览器(ie/chrome),使用URL编码
response.setHeader("Context-Disposition","attachment;filename="
+ URLEncoder.encode(downLoadFileName,"UTF-8"));
}
//5. 读取下载的文件数据,返回给客户端/浏览器
//(1) 创建一个和要下载的文件,关联的输入流
InputStream resourceAsStream = servletContext.getResourceAsStream(downLoadFullPath);
//(2) 得到返回数据的输出流,
ServletOutputStream outputStream = response.getOutputStream();
//(3) 使用工具类, 将输入流关联的文件, 对拷到输出流,并返回给客户端/浏览器
IOUtils.copy(resourceAsStream,outputStream);
}
}
3. 文件下载注意事项
- 文件下载,比价麻烦的就是文件名中文处理
//如果是火狐浏览器, 则中文编码需要base64
if (request.getHeader("User-Agent").contains("Firefox")) {
response.setHeader("Context-Disposition","attachment;filename==?UTF-8?B?"
+ new BASE64Encoder().encode(downLoadFileName.getBytes("UTF-8")) + "?=");
}else{
//其他主流浏览器(ie/chrome),使用URL编码
response.setHeader("Context-Disposition","attachment;filename="
+ URLEncoder.encode(downLoadFileName,"UTF-8"));
}
- 对于网站的文件,很多文件使用另外为即可下载,对于大文件(文档,视频),会使用下载工具
- 对于不同的浏览器,在把文件下载完毕后,处理的方式不一样,有些是直接打开文件,有些是将文件下载到 本地/下载目录