前端页面
思路:
文件上传的解读
1.还是使用表单提交
2. action还是按照以前规定来指定
3. method指定为post
4. enctype: encodetype编码类型默认是application/x-www-urlencoded即url
编码这种编码不适二进制文件数据的提交,一般是适用文本
5.如果是要进行进制文件的提交enctype要指定multipart/form-data表示表单提交的数据是有多个部分组成,也就是可以提交二进制数据和文本数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 指定了base标签 -->
<base href="<%=request.getContextPath()+"/"%>>">
<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];
//获取文件阅读器: Js的一个类,直接使用即可
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
enctype="multipart/form-data" 表示提交的数据是多个部分构造,有文件和文本
-->
<form action="fileUploadServlet" method="post" enctype="multipart/form-data">
家居图: <img src="2.jpg" alt="" width="200" height="200" id="prevView">
<%-- 小伙伴愿意完成自己测试--%>
<input type="file" name="pic" id="" value="" onchange="prev(this)"/>
家居名: <input type="text" name="name"><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
后端servlet(详细看代码,每一句是干啥都要知道)
思路:
1.判断是不是一个文件表单
2.判断表单提交的各个表单项是什么类型
3.如果是个普通的表单项,就按照文本的方式来处理
4.如果是一个文件表单项(进制数据),使用I0技术问进行处理
5.把表单提交的文件数据,保存到你指定的服务端的某个目录
(注意:1.为了防止文件覆盖,在保存文件时 文件名加个前缀2.文件按日期分)
package com.hspedu.servlet;
import com.hspedu.utils.WebUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
public class FileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//System.out.println("FileUploadServlet 被调用...");
//1. 判断是不是文件表单(enctype="multipart/form-data")
if (ServletFileUpload.isMultipartContent(request)) {
//System.out.println("OK");
//2. 创建 DiskFileItemFactory 对象, 用于构建一个解析上传数据的工具对象
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//3. 创建一个解析上传数据的工具对象
/**
* 表单提交的数据就是 input 元素
* <input type="file" name="pic" id="" value="2xxx.jpg" onchange="prev(this)"/>
* 家居名: <input type="text" name="name"><br/>
* <input type="submit" value="上传"/>
*/
ServletFileUpload servletFileUpload =
new ServletFileUpload(diskFileItemFactory);
//解决接收到文件名是中文乱码问题
servletFileUpload.setHeaderEncoding("utf-8");
//4. 关键的地方, servletFileUpload 对象可以把表单提交的数据text / 文件
// 将其封装到 FileItem 文件项中
// 老师的编程心得体会: 如果我们不知道一个对象是什么结构[1.输出 2.debug 3. 底层自动看到]
try {
List<FileItem> list = servletFileUpload.parseRequest(request);
/*
list==>
[name=3.jpg, StoreLocation=D:\hspedu_javaweb\apache-tomcat-8.0.50-windows-x64\apache-tomcat-8.0.50\temp\xupload__7e34374f_17fce4168b1__7f4b_00000000.tmp, size=106398bytes, isFormField=false, FieldName=pic,
name=null, StoreLocation=D:\hspedu_javaweb\apache-tomcat-8.0.50-windows-x64\apache-tomcat-8.0.50\temp\xupload__7e34374f_17fce4168b1__7f4b_00000001.tmp, size=6bytes, isFormField=true, FieldName=name]
*/
//System.out.println("list==>" + list);
//遍历,并分别处理=> 自然思路
for (FileItem fileItem : list) {
//System.out.println("fileItem=" + fileItem);
//判断是不是一个文件=> 你是OOP程序员
if (fileItem.isFormField()) {//如果是true就是文本 input text
String name = fileItem.getString("utf-8");
System.out.println("家具名=" + name);
} else {//是一个文件
//用一个方法
//获取上传的文件的名字
String name = fileItem.getName();
System.out.println("上传的文件名=" + name);
//把这个上传到 服务器的 temp下的文件保存到你指定的目录
//1.指定一个目录 , 就是我们网站工作目录下
String filePath = "/upload/";
//2. 获取到完整目录 [io/servlet基础]
// 这个目录是和你的web项目运行环境绑定的. 是动态.
//fileRealPath=D:\hspedu_javaweb\fileupdown\out\artifacts\fileupdown_war_exploded\xupload\
String fileRealPath =
request.getServletContext().getRealPath(filePath);
System.out.println("fileRealPath=" + fileRealPath);
//3. 创建这个上传的目录=> 创建目录?=> Java基础
// 老师思路; 我们也一个工具类,可以返回 /2024/11/11 字符串
File fileRealPathDirectory = new File(fileRealPath + WebUtils.getYearMonthDay());
if (!fileRealPathDirectory.exists()) {//不存在,就创建
fileRealPathDirectory.mkdirs();//创建
}
//4. 将文件拷贝到fileRealPathDirectory目录
// 构建一个上传文件的完整路径 :目录+文件名
// 对上传的文件名进行处理, 前面增加一个前缀,保证是唯一即可, 不错
// UUID.randomUUID().toString() + "_" +System.currentTimeMillis()是为了加个前缀,防止文件覆盖
name = UUID.randomUUID().toString() + "_" +System.currentTimeMillis() + "_" + name;
String fileFullPath = fileRealPathDirectory + "/" +name;
fileItem.write(new File(fileFullPath));
//5. 提示信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("上传成功~");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("不是文件表单...");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
后端工具类
说明:
以字符串的格式 返回当前的日期
package com.hspedu.utils;
import java.time.LocalDateTime;
public class WebUtils {
public static String getYearMonthDay() {
//如何得到当前的日期-> java基础 日期 三代类
LocalDateTime ldt = LocalDateTime.now();
int year = ldt.getYear();
int monthValue = ldt.getMonthValue();
int dayOfMonth = ldt.getDayOfMonth();
String yearMonthDay = year + "/" + monthValue + "/" + dayOfMonth + "/";
return yearMonthDay;
}
//技巧, 最好测试一把
//public static void main(String[] args) {
// System.out.println(WebUtils.getYearMonthDay());
//}
}
文件上传注意事项和细节
1. 如果将文件都上传到一个目录下,当上传文件很多时,会造成访问文件速度变慢,因此可以将文件上传到不同目录 比如 一天上传的文件,统一放到一个文件夹年月日, 比如21001010 文件夹
2. 一个完美的文件上传,要考虑的因素很多,比如断点续传、控制图片大小,尺寸,分片 上传,防止恶意上传等,在项目中,可以考虑使用
WebUploader
组件
(
百度开发
)
http://fex.baidu.com/webuploader/doc/index.html
3. 文件上传功能,在项目中建议有限制的使用,一般用在头像、证明、合同、产品展示等, 如果不加限制,会造成服务器空间被大量占用
[
比如
b
站评论,就不能传图片,微信发 1 次朋友圈最多
9
张图等
..]
4
、文件上传,创建
web/upload
的文件夹,在
tomcat
启动时,没有在
out 目录下 创建 对 应的
upload
文件夹
,
原因是
tomcat
对应空目录是不会在
out 下创建相应目录的,所以,只需在
upload
目录下,放一个文件即可
,
这个是
Idea + Tomcat
的问题
,
实际开发不会存
在