今天我們來學習Servlet文件上傳下載
Servlet文件上傳主要是使用了ServletInputStream讀取流的方法,其讀取方法與普通的文件流相同。
一.文件上傳相關原理
第一步,構建一個upload.jsp文件
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form enctype="application/x-www-form-urlencoded" action="${pageContext.request.contextPath }/servlet/UploadServlet1" method="post">
<input type="text" name="name" value="name" /><br/>
<div id="div1">
<div>
<input type="file" name="photo" />
</div>
</div>
<input type="submit" name="上傳" /><br/>
</form>
</body>
</html>
第二步,構建一個servlet UploadServlet1.java
package com.zk.upload;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UploadServlet1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name=request.getParameter("name");
String photo=request.getParameter("photo");
ServletInputStream inputstream=request.getInputStream();
int len=0;
byte[] b=new byte[1024];
while((len=inputstream.read(b))!=-1){
System.out.println(new String(b,0,len));
}
inputstream.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletInputStream inputstream=request.getInputStream();
int len=0;
byte[] b=new byte[1024];
while((len=inputstream.read(b))!=-1){
System.out.println(new String(b,0,len));
}
inputstream.close();
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
最后執行UploadServlet1.java之后,輸出上傳文件的信息。

這里涉及到文件上傳的相關原理,在我本地瀏覽器中調試顯示信息如下:




這是一些有關文件上傳的相關信息。
二.文件上傳
接下來,我們開始進行文件上傳的工作。
第一部,創建jsp
這里的form表單需要更改一下enctype屬性,這個屬性是規定在發送到服務器之前應該如何對表單數據進行編碼。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<form enctype="multipart/form-data" action="${pageContext.request.contextPath }/servlet/UploadServlet2" method="post">
<input type="text" name="name" value="name" /><br/>
<div id="div1">
<div>
<input type="file" name="photo" />
</div>
</div>
<input type="submit" name="上傳" /><br/>
</form>
</body>
</html>
UploadServlet2.java
package com.zk.upload;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
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;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
public class UploadServlet2 extends HttpServlet {
/**
* Constructor of the object.
*/
public UploadServlet2() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//優先級不高
request.setCharacterEncoding("UTF-8");
//要執行文件上傳的操作
//判斷表單是否支持文件上傳
boolean isMultipartContent=ServletFileUpload.isMultipartContent(request);
if(!isMultipartContent){
throw new RuntimeException("your form is not multipart/form-data");
}
//創建一個DiskFileItemFactory工廠類
DiskFileItemFactory factory=new DiskFileItemFactory();
//創建一個ServletFileUpload核心對象
ServletFileUpload sfu=new ServletFileUpload(factory);
//解決上傳表單亂碼的問題
sfu.setHeaderEncoding("UTF-8");
try {
//限制上傳文件的大小
//sfu.setFileSizeMax(1024);
//sfu.setSizeMax(6*1024*1024);
//解析requst對象,得到一個表單項的集合
List<FileItem> fileitems=sfu.parseRequest(request);
//遍歷表單項數據
for(FileItem fileItem:fileitems){
if(fileItem.isFormField()){
//普通表單項
processFormField(fileItem);
}
else{
//上傳表單項
processUploadField(fileItem);
}
}
} catch(FileUploadBase.FileSizeLimitExceededException e){
throw new RuntimeException("文件過大");
}catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void processUploadField(FileItem fileItem) {
// TODO Auto-generated method stub
//得到上傳的名字
String filename=fileItem.getName();
//得到文件流
try {
InputStream is=fileItem.getInputStream();
String dictory=this.getServletContext().getRealPath("/upload");
System.out.println(dictory);
//創建一個存盤的路徑
File storeDirecctory=new File(dictory);//既代表文件又代表目錄
if(!storeDirecctory.exists()){
storeDirecctory.mkdirs();//創建一個指定目錄
}
//處理文件名
filename=filename.substring(filename.lastIndexOf(File.separator)+1);
if(filename!=null){
filename=FilenameUtils.getName(filename);
}
//解決文件同名的問題
filename=UUID.randomUUID()+"_"+filename;
//目錄打散
//String childDirectory=makeChildDirectory(storeDictory);//2015-10-
String childDirectory=makeChildDirectory2(storeDirecctory,filename);
//System.out.println(childDirectory);
//上傳文件,自動刪除臨時文件
fileItem.write(new File(storeDirecctory,childDirectory+File.separator+filename));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//上傳表單項
private void processUploadField1(FileItem fileItem) {
// TODO Auto-generated method stub
//得到上傳的名字
String filename=fileItem.getName();
//得到文件流
try {
//得到文件流
InputStream is=fileItem.getInputStream();
String dictory=this.getServletContext().getRealPath("/upload");
System.out.println(dictory);
//創建一個存盤的路徑
File storeDictory=new File(dictory);//既代表文件又代表目錄
if(!storeDictory.exists()){
storeDictory.mkdirs();//創建一個指定目錄
}
//處理文件名
filename=filename.substring(filename.lastIndexOf(File.separator)+1);
if(filename!=null){
filename=FilenameUtils.getName(filename);
}
//解決文件同名的問題
filename=UUID.randomUUID()+"_"+filename;
//目錄打散
//String childDirectory=makeChildDirectory(storeDictory);//2015-10-
String childDirectory2=makeChildDirectory2(storeDictory,filename);
//System.out.println(childDirectory);
//在storeDictory目錄下創建完整的文件
//File file=new File(storeDictory,filename);
//File file=new File(storeDictory,childDirectory+File.separator+filename);
File file2=new File(storeDictory,childDirectory2+File.separator+filename);
//通過文件輸出流將上傳的文件保存到磁盤
//FileOutputStream fos=new FileOutputStream(file);
FileOutputStream fos2=new FileOutputStream(file2);
int len=0;
byte[] b=new byte[1024];
while((len=is.read(b))!=-1){
// fos.write(b,0,len);
fos2.write(b,0,len);
}
//fos.close();
fos2.close();
is.close();
System.out.println("success");
//刪除臨時文件
fileItem.delete();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//目錄打散
private String makeChildDirectory(File storeDictory) {
// TODO Auto-generated method stub
SimpleDateFormat sm=new SimpleDateFormat("yyyy-MM-dd");
String date=sm.format(new Date());
//創建目錄
File file=new File(storeDictory,date);
if(!file.exists()){
file.mkdirs();
}
return date;
}
//目錄打散
private String makeChildDirectory2(File storeDictory,String filename){
int hashcode=filename.hashCode();
System.out.println(hashcode);
String code=Integer.toHexString(hashcode);
String childDirectory=code.charAt(0)+File.separator+code.charAt(1);
//創建指定目錄
File file=new File(storeDictory,childDirectory);
if(!file.exists()){
file.mkdirs();
}
return childDirectory;
}
//普通表單項
private void processFormField(FileItem fileItem) {
// TODO Auto-generated method stub
String fieldname=fileItem.getFieldName();
try {
String valuename=fileItem.getString("UTF-8");
// fieldname=new String(valuename.getBytes("iso-8859-1"),"utf-8");
System.out.println(fieldname+":"+valuename);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//要執行文件上傳的操作
//判斷表單是否支持文件上傳
boolean isMultipartContent=ServletFileUpload.isMultipartContent(request);
if(!isMultipartContent){
throw new RuntimeException("your form is not multipart/form-data");
}
//創建一個DiskFileItemFactory工廠類
DiskFileItemFactory factory=new DiskFileItemFactory();
//產生臨時文件
factory.setRepository(new File("f:\\temp"));
//創建一個ServletFileUpload核心對象
ServletFileUpload sfu=new ServletFileUpload(factory);
sfu.setHeaderEncoding("UTF-8");
try {
//限制上傳文件的大小
//sfu.setFileSizeMax(1024*1024*1024);
//sfu.setSizeMax(6*1024*1024);
//解析requst對象,得到一個表單項的集合
List<FileItem> fileitems=sfu.parseRequest(request);
//遍歷表單項數據
for(FileItem fileItem:fileitems){
if(fileItem.isFormField()){
//普通表單項
processFormField(fileItem);
}
else{
//上傳表單項
processUploadField(fileItem);
}
}
} catch(FileUploadBase.FileSizeLimitExceededException e){
//throw new RuntimeException("文件過大");
System.out.println("文件過大");
}catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
這里面加了文件大小限制、文件重命名、目錄打散等方法。
最后,我們運行一下這個demo

我們在web-apps的目錄下可以看到我們剛剛上傳的文件

三.文件下載
現在我們進行文件下載
package com.zk.upload;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet1 extends HttpServlet {
/**
* Constructor of the object.
*/
public DownloadServlet1() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//設置一個要下載的文件
String filename="a.csv";
filename=new String(filename.getBytes("UTF-8"),"iso-8859-1");
//告知瀏覽器要下載文件
response.setHeader("content-disposition", "attachment;filename="+filename);
response.setContentType(this.getServletContext().getMimeType(filename));//根據文件明自動獲取文件類型
response.setCharacterEncoding("UTF-8");//告知文件用什么服務器編碼
PrintWriter pw=response.getWriter();
pw.write("Hello,world");
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
首先指定一個需要下載的文件的文件名,然后告知瀏覽器需要下載文件,根據文件明自動獲取文件類型,並告知文件用什么服務器編碼。執行servlet后,會下載一個名為
a.csv的文件。

下載后,可以看到文件中存有Hello,world字符。

