上传文件的要求
表单的要求
1.表单的提交方式必须为POST方式
2.必须添加表单的另一属性enctype=”multipart/form-data”
Servlet的要求
1.若表单中加属性enctype,则在Servlet无法使用req.getParameter(“xxx”)方法,任何表单项都会返回null。
2.在Servlet提供了另外一种获取表单数据的方法req.getInputStream(),得到的是整个请求体。
需要的jar包
commons-fileupload-1.2.2.jar
commons-io-2.6.jar
commons-fileupload介绍
-
从表单中获取请求体数据后,我们需要借助该包对请求体解析,解析完成后的数据存放在
FileItem对象当中,只需要用该对象的具体方法即可以得到我们想要的表单数据。
如何获得FileItem对象?
-
1.创建工厂:DiskFileItemFactory dff = new DiskFileItemFactory();
2.创建解析器:ServletFileUpload sfu = new ServletFileUpload(dff);
3.得到FileItem类型的LIst:List<FileItem> list = sfu.parseRequest(request)
4.遍历List,获得需要的数据。
FileItem介绍(不完全介绍)
方法 | 作用 |
---|---|
getFieldName() | 返回当前表单项的名称 |
getName() | 返回上传文件的名称 |
getString(String charset) | 获得当前表单项的值 |
isFormField() | 是否是普通表单项 |
getSize() | 返回上传文件的大小(字节数) |
getInputStream() | 返回上传文件对应的输入流 |
write(File file) | 把上传的文件保存到指定文件中 |
示例:
<body>
<h1>上传文件</h1>
<form action='<c:url value='/UpLoadServlet'></c:url>' method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br>
照片:<input type="file" name="photo"><br>
<input type="submit" value="上传">
</form>
</body>
package tqb.upload.web.servlet;
import java.io.File;
import java.io.IOException;
import java.util.List;
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.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@WebServlet("/UpLoadServlet")
public class UpLoadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//处理post请求编码
request.setCharacterEncoding("utf-8");
// 创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 创建解析器
ServletFileUpload sfu = new ServletFileUpload(factory);
// 获得Fileitem类型的List
try {
List<FileItem> list = sfu.parseRequest(request);
FileItem f1 = list.get(0);
FileItem f2 = list.get(1);
System.out.println("普通表单项:" + f1.getFieldName() + "=" + f1.getString("utf-8"));
System.out.println("文件表单项:");
System.out.println("Content-Type:" + f2.getContentType());
System.out.println(f2.getName());
System.out.println(f2.getSize());
try {
f2.write(new File("C:\\Users\\lenovo\\Desktop\\photo.jpg"));
} catch (Exception e) {
throw new RuntimeException(e);
}
} catch (FileUploadException e) {
throw new RuntimeException(e);
}
}
}
上传文件的细节
-
1.文件必须保存到WEB-INF中,避免用户可以从浏览器可以直接访问
2.文件名称相关问题
- a.有的浏览器上传文件的文件名是绝对路径,需要切割!如:C:\hello\hello.txt
- b.文件乱码或普通表单项乱码,解决办法: req.setCharacterEncoding(“utf-8”);
- c.文件同名问题:解决办法: uuid 3.目录打散,不要在一个目录下放过多的文件 4.上传文件的大小限制
- a.单个文件的大小限制
- b.整个请求数据的大小限制
5.缓存大小与临时目录
代码实现:
package tqb.upload.web.servlet;
import java.io.File;
import java.io.IOException;
import java.util.List;
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.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import cn.itcast.commons.CommonUtils;
@WebServlet("/UpLoadServlet")
public class UpLoadServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//编码设置
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
//创建工厂
// DiskFileItemFactory factory = new DiskFileItemFactory();
//缓存大小与临时目录,第一个参数为上传文件大小超过多少时会在硬盘建立缓存目录(默认为10kb),第二个参数为缓存目录的位置
DiskFileItemFactory factory = new DiskFileItemFactory(20 * 1024, new File("D:/temp"));
//创建解析器
ServletFileUpload sfu = new ServletFileUpload(factory);
//限制单个文件的上传大小(1M)
// sfu.setFileSizeMax(1024 * 1024);
//限制整体请求体的大小(2M)
// sfu.setSizeMax(2048 * 1024);
//得到List
try {
List<FileItem> list = sfu.parseRequest(request);
FileItem f1 = list.get(0);
FileItem f2 = list.get(1);
//得到普通表单项名称
// f1.getFieldName();
//得到普通表单项值
// f1.getString();
//得到文件根目录
String root = this.getServletContext().getRealPath("/WEB-INF/files");
//得到文件表单项名称
String upName = f2.getName();
//处理文件上传是带路径名
int index = upName.lastIndexOf("\\");
if (index != -1){
upName = upName.substring(index + 1);
}
//处理文件同名问题,保存就按这个保存
String newName = CommonUtils.uuid() + "_" + upName;
//哈希方法打散目录
/*
* 1.获取哈希值,转16进制
* 2.分别得到前两个字符
* 3.创建目录
* 4.将上传得文件保存到目录之中
*/
int hashCode = newName.hashCode();
String hexString = Integer.toHexString(hashCode);
File path = new File(root,hexString.charAt(0) + "/" + hexString.charAt(1));
//有该文件得话不创建,没有的话自动创建
path.mkdirs();
//将文件保存在指定位置
try {
f2.write(new File(path,newName));
} catch (Exception e) {
e.printStackTrace();
}
} catch (FileUploadException e) {
if (e instanceof FileSizeLimitExceededException){
request.setAttribute("msg", "文件大小超过1M,上传失败!");
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
if(e instanceof SizeLimitExceededException){
request.setAttribute("msg", "整体大小超过2M,上传失败!");
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
}
}
}
邮件的发送
-
有关于邮件的协议
- SMTP 简单邮件传输协议 发邮件的协议 端口号:25 服务器名称为:stmp.xxx.xxx 如:stmp.163.com
- POP3 邮局协议第三版 收邮件的协议 端口号:110 服务器名称:pop3.xxx.xxx 如:pop3.163.com
- IMAP 因特网消息访问协议 收发邮件的协议(了解) 依赖的jar包:
- javax.mail-1.6.2.jar
- activation-1.1.1.jar
不带附件的邮件
package tqb.mail;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.junit.Test;
/**
* 邮件的发送(不带附件)
* @author tqb
*
*/
public class MyMail {
/*
*
*/
@Test
public void fun() throws AddressException, MessagingException{
/*
* 1.获得Session
*/
Properties props = new Properties();
props.setProperty("mail.host", "smtp.163.com");
props.setProperty("mail.smtp.auth", "true");
Authenticator auth = new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
/*
* 用户名,密码
*/
return new PasswordAuthentication("username", "password");
}
};
Session session = Session.getInstance(props, auth);
/*
* 2.获得MimeMessage
*/
MimeMessage msg = new MimeMessage(session);
//发件人
msg.setFrom(new InternetAddress("tqb820965236@163.com"));
//收件人
msg.setRecipients(RecipientType.TO, "820965236@qq.com");
//抄送人
// msg.setRecipients(RecipientType.CC, "");
//暗送人(看不到,但是会收到消息)
// msg.setRecipients(RecipientType.BCC, "");
//标题
msg.setSubject("这是一个测试邮件");
//正文
msg.setContent("邮件正文,测试邮件,不要理会!!!", "text/html;charset=utf-8");
/*
* 3.发送邮件
*/
Transport.send(msg);
}
}
带附件的邮件
package tqb.mail;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import org.junit.Test;
/**
* 发送带有附件的邮件
* @author tqb
*
*/
public class MyMail2 {
@Test
public void fun() throws MessagingException, IOException{
/*
* 创建Session
*/
Properties props = new Properties();
props.setProperty("mail.host", "smtp.163.com");
props.setProperty("mail.smtp.auth", "true");
Authenticator auth = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username","password");
}
};
Session session = Session.getInstance(props, auth);
/*
* 得到mimeMessage
*/
MimeMessage msg = new MimeMessage(session);
msg.setSubject("带附件的邮件");
//创建多部分主体
MimeMultipart list = new MimeMultipart();
//创建MimeBodyPart
MimeBodyPart part1 = new MimeBodyPart();
part1.setContent("这是带有附件的垃圾邮件","text/html;charset=utf-8");
MimeBodyPart part2 = new MimeBodyPart();
//附件
part2.attachFile(new File("C:\\Users\\lenovo\\Desktop\\dogcom.exe"));
//附件的名称+编码(防止乱码)
part2.setFileName(MimeUtility.encodeWord("狗子.exe"));
//将MimeBodyPart添加至MimeMultipart
list.addBodyPart(part1);
list.addBodyPart(part2);
msg.setContent(list);
msg.setFrom(new InternetAddress("tqb820965236@163.com"));
msg.setRecipients(RecipientType.TO, "820965236@qq.com");
/*
* 发送邮件
*/
Transport.send(msg);
}
}