JSP 可以與 HTML form 標(biāo)簽一起使用,來(lái)允許用戶(hù)上傳文件到服務(wù)器。上傳的文件可以是文本文件或圖像文件或任何文檔。
需要引入的 jar 文件:commons-fileupload-1.3.2、commons-io-2.5.jar
I/O基礎(chǔ)知識(shí)
I(Input輸入)/O(Output輸出):I/O流 輸入流/輸出流
- 對(duì)文件的讀操作:使用輸入流
- 對(duì)文件的寫(xiě)操作:使用輸出流
流的分類(lèi)
輸入流(InputStream)/輸出流(OutputStream)
字節(jié)流/字符流:例如對(duì)圖片進(jìn)行操作(copy)使用字節(jié)流 對(duì)普通文件的操作可以使用字符流
節(jié)點(diǎn)流/處理流:節(jié)點(diǎn)流會(huì)直接關(guān)聯(lián)到數(shù)據(jù)源上而處理流是對(duì)節(jié)點(diǎn)流功能的增強(qiáng)(不會(huì)直接關(guān)聯(lián)數(shù)據(jù)源)
節(jié)點(diǎn)流
//使用FileInputStream對(duì)數(shù)據(jù)源讀取字節(jié)
FileInputStream fis = new FileInputStream("b1.jpg");
//使用FileOutputStream向目標(biāo)文件寫(xiě)字節(jié)
FileOutputStream fos = new FileOutputStream("b1_demo.jpg");
處理流
fr = new FileReader("Test.java");//源文件
br = new BufferedReader(fr);//處理流對(duì)fr節(jié)點(diǎn)流功能的增強(qiáng)
FileWriter fw = new FileWriter("Test_New.java");//目標(biāo)文件
BufferedWriter bw = new BufferedWriter(fw);//處理流對(duì)fw節(jié)點(diǎn)流功能的增強(qiáng)
- 在API中凡是以InputStream/OutputStream結(jié)尾的都是字節(jié)流
- 凡是以Reader/Writer結(jié)尾的都是字符流
- InputStream、 OutputStream、 Reader、Writer這四個(gè)類(lèi),是這兩大繼承體系的父類(lèi)
- 所有字節(jié)流的根父類(lèi)為:InputStream、 OutputStream
- 所有字符流的根父類(lèi)為: Reader、Writer
創(chuàng)建一個(gè)文件上傳表單
需要注意:
表單 method 屬性應(yīng)該設(shè)置為 POST 方法,不能使用 GET 方法。
表單 enctype 屬性應(yīng)該設(shè)置為 multipart/form-data.
表單 action 屬性應(yīng)該設(shè)置為在后端服務(wù)器上處理文件上傳的 Servlet 文件。
上傳單個(gè)文件,您應(yīng)該使用單個(gè)帶有屬性 type="file" 的 <input .../> 標(biāo)簽。為了允許多個(gè)文件上傳,請(qǐng)包含多個(gè) name 屬性值不同的 input 標(biāo)簽。輸入標(biāo)簽具有不同的名稱(chēng)屬性的值。瀏覽器會(huì)為每個(gè) input 標(biāo)簽關(guān)聯(lián)一個(gè)瀏覽按鈕。
Servlet
package com.foreknow.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
/**
* Created by foreknow on 2018/12/13.
MultipartConfig
使用注解MultipartConfig 將一個(gè) Servlet 標(biāo)識(shí)為支持文件上傳。Servlet3.0 將
multipart/form-data 的 POST 請(qǐng)求封裝成 Part,通過(guò) Part 對(duì)文件進(jìn)行上傳。
Servlet3 沒(méi)有提供直接獲取文件名的方法,需要從請(qǐng)求頭中解析出來(lái)
*/
@WebServlet(name = "UploadServlet",urlPatterns = "/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part part = request.getPart("file");
String name = part.getSubmittedFileName();
UUID uuid = UUID.randomUUID();
String path = request.getServletContext().getRealPath("")+"/pic/";
File file = new File(path);
if (!file.exists()){
file.mkdirs();
}
part.write(path+uuid+name);
response.getWriter().print(uuid+name);
request.getSession().setAttribute("pic",uuid+name);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
注意可能遇到的問(wèn)題
在tomcat8使用servlet3.0上傳文件,原來(lái)按以下步驟就可以完成
1.Part part = request.getPart("XX");
2.part.getSubmittedFileName()//直接獲取文件名
3.part.write(realPath)
在tomcat7 的環(huán)境下就沒(méi)有part.getSubmittedFileName()這一方法,無(wú)法直接獲取文件名
解決方案:
String cd = part.getHeader("Content-Disposition");
//截取不同類(lèi)型的文件需要自行判斷
String filename = cd.substring(cd.lastIndexOf("=")+2, cd.length()-1);
upload.jsp
<%--
User: foreknow
Date: 2018/12/13
Time: 9:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script>
window.onload = function () {
document.querySelector("#file").onchange = function () {
var req = new XMLHttpRequest();
var form = new FormData(document.getElementById("form1"));
// form.append("file",document.querySelector("#file").files[0]);
req.open("post", "${pageContext.request.contextPath}/upload", true);
req.send(form);
req.onload = function () {
document.getElementById("img").src = "${pageContext.request.contextPath}/pic/" + req.responseText;
}
}
}
</script>
<style>
img {
width: 200px;
height: 200px;
border-radius: 50%;
}
</style>
</head>
<body>
<form id="form1" action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
<img id="img" src="${pageContext.request.contextPath}/pic/${pic}"
onerror="this.src='${pageContext.request.contextPath}/b1.jpg'">
<input type="file" name="file" id="file">
</form>
</body>
</html>