Java Web(十一) 文件上傳與下載
文件上傳
上傳的準備工作
- 表單method必須為post
- 提供file組件
- 設置form標簽的enctype屬性為multipart/form-data,如果沒有設置enctype屬性,瀏覽器是無法將文件自身傳遞到服務端的(enctype默認為application/x-www-form-urlencoded)
<form action="fileupload.do" method="post" enctype="multipart/form-data"> 用戶名:<input type="text" name="username"/><br/> 密碼:<input type="password" name="password"/><br/> 上傳文件:<input name="file" type="file" /><br/> <input type="submit"/> </form>
上傳時HTTP協議的格式
enctype為application/x-www-form-urlencoded時
從表單發送數據到服務器,數據是以鍵值對的形式存放在請求體中發送到服務器的。
使用google瀏覽器的自動抓包(F12),可以查看表單數據在HTTP協議中的格式:
request.getParameter(name)是以鍵值對的形式獲取值的,所以可以通過該方法得到表單中的數據。可以得到文件名,但是得不到文件!
enctype為multipart/form-data時
在上傳時,multipart/form-data請求會把表單的數據處理為一條消息,以標簽為單元,用分隔符(boundary)分開。既可以上傳普通表單數據,也可以上傳文件。content-disposition,用來說明字段的一些信息。當上傳的字段是文件時,會有Content-Type來表明文件類型。
使用google瀏覽器查看上傳時表單數據在HTTP協議的格式:
表單數據在HTTP協議中不是以鍵值對形式存在的,所以在服務器端是無法通過request.getParameter(name)獲取數據的。
可以利用分隔符boundary和Content-type屬性自己編寫代碼實現文件上傳。
在服務器端查看從客戶端傳來的表單數據
可以使用request.getInputStream()來獲取從客戶端傳來的數據,可以通過下面的代碼把傳來的數據輸出到控制臺:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { InputStream is = request.getInputStream(); int i = is.read(); while(i != -1) { char c = (char)i; System.out.print(c); i = is.read(); } }
在沒有設置enctype屬性時,傳到服務器的數據為:
文件上傳時,傳到服務器的數據為:
其中的亂碼為二進制數據,也就是要上傳的文件。
FileUpload實現文件上傳
FileUpload 是 Apache commons下面的一個子項目,用來實現Java環境下面的文件上傳功能。
使用FileUpload需要兩個jar包的支持,這裏FileUpload版本為:commons- fileupload-1.2.1,Commons IO版本為:commons-io-1.4。
服務器端代碼為:
@WebServlet(name = "FileServlet",urlPatterns = "/fileupload.do")
public class FileServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//判斷是否支持文件上傳
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if(!isMultipart) {
throw new RuntimeException("不支持文件上傳");
}
//創建一個磁盤工廠
DiskFileItemFactory factory=new DiskFileItemFactory();
//配置緩存庫
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
//解析數據
ServletFileUpload fileUpload=new ServletFileUpload(factory);
List<FileItem> items = null;
try {
items=fileUpload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
for(FileItem item : items) {
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
System.out.println(name + " " + value);
} else {
//取文件名
String fileName = item.getName();
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
//取文件拓展名
String exten = fileName.substring(fileName.lastIndexOf("."));
//新文件名,防止文件重名
String newFileName = UUID.randomUUID().toString().replace("-", "") + exten;
//把文件寫入到upload文件夾下
String path = this.getServletConfig().getServletContext().getRealPath("/");
String directPath = path + "upload\\" + newFileName;
File file = new File(directPath);
OutputStream os = new FileOutputStream(file);
InputStream is = item.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = is.read(b)) != -1) {
os.write(b, 0, len);
}
os.close();
is.close();
}
}
request.getRequestDispatcher("ok.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
文件下載
@WebServlet(name = "DownloadServlet", urlPatterns = "/download.do")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 獲得要下載的文件的名稱
String filename = request.getParameter("filename");
// 告訴客戶端該文件不是直接解析,而是以附件形式打開(下載)
response.setHeader("Content-Disposition", "attachment;filename=" + filename);
// 獲取文件的絕對路徑
String path = this.getServletContext().getRealPath("download/" + filename);
// 獲得該文件的輸入流
InputStream in = new FileInputStream(path);
// 獲得輸出流--通過response獲得的輸出流 用於向客戶端寫內容
ServletOutputStream out = response.getOutputStream();
// 文件拷貝代碼
int len = 0;
byte[] buffer = new byte[1024];
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
in.close();
out.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
Java Web(十一) 文件上傳與下載