1. 程式人生 > >Servlet實現檔案上傳詳解與實戰

Servlet實現檔案上傳詳解與實戰

    檔案上傳

1.客戶端程式設計

要上傳檔案,必須利用mutipart/form-data 設定HTML表單的enctype 屬性值

<form action="action"  enctype="mutipart/form-data"  method="post">

Select a file <input type="file" name="fileName"/>

<input type="submit" value="Upload">

</form>

如果想上傳多個檔案,則不得不使用檔案input元素,在input元素加入multipel屬性 ,以便生成一個按鈕供選擇多個檔案

<input type="file" name="fileName" mutipel/> 

<input type="file" name="fileName" mutipel="multipel"/> 

<input type="file" name="fileName" mutipel=""/>    同樣效果

2. 伺服器端程式設計

Sevlet中的伺服器處理上傳檔案的Servlet必須用 @MutipartConfig 進行標註。 

MutipartConfig帶有下面幾個屬性:

maxFileSize: 表示可上傳檔案的容量。預設為-1,表示不受限制

maxRequestSize:表示允許多部分HTTP請求的最大容量。預設為-1,表示不受限制

location:將上傳的檔案儲存到磁碟中的指點位置,呼叫Part的write方法將用到它

fileSizeThreshold:設定一個溢位尺寸,超過這個值之後,上傳的檔案將被寫入磁碟

在一個有多部分組成的請求中,標一個表單域,包括非檔案域,都會被轉換成一個Part

HttpServletRequest 介面定義了以下方法來處理多部分的請求:

Part getPart (String name)  :返回指點名稱的Part   

Collection getParts()  :返回這個請求的所有PART

Part介面還有以下的方法

String getName()    返回與指定部分有關的域名稱,非檔名稱(要想獲取檔名稱,需要解析content-disposition標頭)

Collection  getHeaderNames()   返回這個part中所有標頭名稱    

String getContentType()   如果part是檔案,則返回檔案的名稱,否則返回null  (用於檢驗一個Part是否為檔案域)

String getHeader(String name)    返回指點name的標頭名稱

Collection getHeaders(String name)   返回這個part中所有標頭名稱 

void write(String path)   將上傳的檔案寫入磁碟中。如果path是個絕對路徑,則寫入,如果path是相對路徑,那麼將被寫入相對MultiConfig註解的location屬性指定的路徑

void delete()    刪除該檔案對應的儲存

java.io.InputStream getInputStream()  以InputStream的形式返回上傳檔案的內容

如果上傳一個名為document的note.txt檔案時,其具有標頭:

content-type:text/plain

content-disposition:form-data;name="document" ;filename="note.txt"

如果沒有選擇檔案,還是會為該檔案域建立一個Part,相關標頭:

content-type:application/octet-stream

content-disposition:form-data;name="document" ;filename=""

對於非檔案的域,Part只有content-disposition標頭

3.例項:上傳Servlet範例

下面例子示範如何編寫一個多部分的Servlet。它可以處理單個檔案上傳

SingleUploadServlet類,實現MutipartConfig 

import java.io.IOException;
import java.io.PrintWriter;

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;
@WebServlet(urlPatterns={"/singleUpload"})
@MultipartConfig
public class SingleUploadServlet extends HttpServlet {
	private static final long serialVersionUID=8593038L;
	
	private String getFilename(Part part){
		String contentDispositoinHeader=part.getHeader("content-disposition");
		String [] elements=contentDispositoinHeader.split(";");
		for(String element:elements){
			if(element.trim().startsWith("filename")){
				return element.substring(
						element.indexOf('=')+1).trim().replace("\"", "");
			}
		}
		return null;
	}
	
	
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		Part part=req.getPart("filename");
		String fileName=getFilename(part);
		if(fileName!=null&&!fileName.isEmpty()){
			part.write(getServletContext().getRealPath("/WEB-INF")+"/"+fileName);
		}
		resp.setContentType("text/html");
		PrintWriter writer=resp.getWriter();
		writer.print("<br/>Uploaded file name:"+fileName);
		writer.print("<br/>Size:"+part.getSize());
		
		String author=req.getParameter("author");
		writer.print("<br/>Author:"+author);
	}



singleUpload.jsp頁面

<body>
    <h1>Select a file to upload</h1>
    <form action="singleUpload" enctype="multipart/form-data" 
    method="post">
    Author:<input type="text" name="author"><br>
    Select a file to upload <input type="file" name="filename "   ><br>
    <input type="submit" value="Upload" ></form>
  </body>


4.多檔案上傳

與前一個例子相似,只不過它是遍歷Part集合,努力核實Part是包含一個檔案還是一個域值

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;

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;
@WebServlet(urlPatterns={"/multipleUploads"})
@MultipartConfig
public class MultipleUploadsServlet extends HttpServlet {

	private static final long serialVersionUID=9991L;
	
	private String getFilename(Part part){
		String contentDispositoinHeader=part.getHeader("content-disposition");
		String [] elements=contentDispositoinHeader.split(";");
		for(String element:elements){
			if(element.trim().startsWith("filename")){
				return element.substring(
						element.indexOf('=')+1).trim().replace("\"", "");
			}
		}
		return null;
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		resp.setContentType("text/html");
		PrintWriter writer=resp.getWriter();
		
		Collection<Part> parts=req.getParts();
		for(Part part:parts){
			if(part.getContentType()!=null){
				String fileName=getFilename(part);
				if(fileName!=null&&!fileName.isEmpty()){
					part.write(getServletContext().getRealPath("/WEB-INF")+"/"+fileName);
				writer.print("<br/>Uploader file name:"+fileName);
				writer.print("<br/>Size:"+part.getSize());
			}
		}else{
		    //假如不存在內容型別,則意味著Part表示的是一個非檔案域
			String partName=part.getName();
			String filedValue=req.getParameter(partName);
			writer.print("<br/>"+partName+":"+filedValue);
			
		}
		}
	}
}
multipelUploads.jsp
<body>
    <h1>Select a file to upload</h1>
    <form action="multipleUploads" enctype="multipart/form-data" method="post">
    Author:<input name="author"><br>
    First file to upload <input type="file" name="filename"><br>
    Second file to upload<input type="file" name="filename"><br>
    <input type="submit" value="Upload"></form>
  </body>