第十章_文件上传
10.1、client編程
要上傳文件,必須利用multipart/form-data設置HTML表單的enctype的屬性值,像以下這樣:
<form action="action" enctype="multipart/form-data" method="post">Select a file<input type="file" name="fieldName" /><input type="submit" value="Upload" /></form>
10.2、server端編程
Servlet中的server端文件上傳編程主要環繞著MultipartConfig注解類型和javax.servlet.http.Part接口進行。
處理上傳文件的Servlet必須用@MultipartConfig進行標注。MultipartConfig能夠帶有下面屬性。這些都是可選的。
maxFileSize,表示最多可上傳的文件容量。超過設定值的文件將會遭到拒絕。
默認值為-1,表示不受限制。
maxRequestSize。表示同意多部分HTTP請求的最大容量。
它的默認值為-1。不受限制。
Location。上傳的文件保存到磁盤的指定位置,調用Part中的write方法將用到它。
fileSizeThreshold。設定一個溢出尺寸,超過這個值之后。上傳的文件將被寫入磁盤。
在一個由多部分組成的請求中,每個表單域,包含非文件域,都會被轉換成一個Part,HttpServletRequest接口定義了下面方法來處理多部分的請求:
Part?getPart(java.lang.String?name)
返回與指定名稱相關的Part。
java.util.Collection<Part>?getParts()
返回這個請求中全部的part
Part接口中還具有下面方法:
java.lang.String?getName()
獲取到這部分的名稱。比如相關表單域的名稱
java.lang.String?getContentType()
假設Part是一個文件,那么將返回Part的內容類型,否則返回null。
java.util.Collection<java.lang.String>?getHeaderNames()
返回這個Part中的全部標頭名稱
java.lang.String?getHeader(java.lang.String?headerName)
返回指定標頭名稱的值
java.util.Collection<java.lang.String>?getHeaders(java.lang.String?headerName)
返回這個Part中全部標頭的名稱
Void?write(java.lang.String?path)
將上傳的文件寫入磁盤中。假設path是一個絕對路徑,那么將寫入指定的路徑。
假設path是一個相對路徑。那么將被寫入相對于MultiConfig注解的location屬性值的指定路徑。
Void?delete()
刪除該文件相應的存儲,包含相關的暫時文件。
java.io.InputStream?getInputStream()
以inputStream的形式返回上傳文件的內容
假設相關的HTML輸入時一個文件input元素,則Part將返回這些標頭:
content-type:contentType
content-disposition:form-data;?name=”fieldName”;?fileName=”fileName”?
比如,上傳輸入域中一個名稱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接口的getName返回與這部分有關的域的名稱,而不是上傳文件的名稱。要想返回后者,須要解析content-disposition標頭,其格式例如以下:
content-disposition:form-data;?name=”fieldName”
在Servlet中處理上傳文件時,須要:
1、查看石頭存在content-type標頭。檢驗一個Part是屬于普通的表單域買還是文件域。你也能夠通過在Part中調用getContentType方法或者getHeader(“content-type”)來完畢檢查。
2、假設有content-type標頭,那么將查看上傳文件名稱稱是否為空。文件名稱為空,表示有文件類型的域存在,可是沒有選擇要上傳的文件。
3、假設文件存在。就能夠調用Part中的write方法來寫入磁盤。調用時同一時候傳遞一個絕對路徑,或是相對于MultipartConfig注解的location屬性的路徑。
?
11.3、上傳Servlet范例
SingleUploadServlet.java
package app11a.servlet;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 = 1L;/*** 通過part過得文件名* @param part* @return*/private String getFileName(Part part){String contentDispositionHeader = part.getHeader("content-disposition") ;String[] elements = contentDispositionHeader.split(";") ;for(String element: elements){if(element.trim().startsWith("filename")){return element.substring(element.indexOf('=') + 1).trim().replace("\"", "") ;}}return null ;}@Overridepublic void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {req.setCharacterEncoding("utf-8") ;resp.setCharacterEncoding("utf-8") ;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/>Upload file name: " + fileName) ;writer.print("<br/>Size: " + part.getSize()) ;String author = req.getParameter("author") ;writer.print("<br/>Author: " + author) ;}}singleUplpad.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html><head><title>My JSP 'singleUpload.jsp' starting page</title></head><body><h1>Select a file to upload</h1><form action="singleUpload" method="post" enctype="multipart/form-data">Author: <input type="text" name="author"/><br/>Select file to upload <input type="file" name="filename"/><br/><input type="submit" value="上傳"/></form></body> </html>
11.4、多文件上傳
MultipleUploadsServlet.javapackage app11a.servlet;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 = 1L;private String getFileName(Part part){String contentDispositionHeader = part.getHeader("content-disposition") ;String[] elements = contentDispositionHeader.split(";") ;for(String element: elements){if(element.trim().startsWith("filename")){return element.substring(element.indexOf('=') + 1).trim().replace("\"", "") ;}}return null ;}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{request.setCharacterEncoding("utf-8") ;response.setCharacterEncoding("utf-8") ;response.setContentType("text/html") ;PrintWriter writer = response.getWriter() ;Collection<Part> parts = request.getParts() ;for(Part part : parts){//通過getContentType獲得是否是文件域if(part.getContentType() != null){String fileName = getFileName(part) ;//通過文件名稱獲得是否有文件if(fileName != null && ! fileName.isEmpty()){part.write(getServletContext().getRealPath("/WEB-INF") + "/" + fileName) ;writer.print("<br/>Uploaded file name: " + fileName) ;writer.print("<br/>Size: " + part.getSize()) ;}}else{String partName = part.getName() ;String fieldValue = request.getParameter(partName) ;writer.print("<br/>" + partName + ": " + fieldValue) ;}}}}
multipleUploads.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html><head><title>My JSP 'multipleUploads.jsp' starting page</title></head><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="uploadFile"/><br/>Second file to upload <input type="file" name="uploadFile2"/><br/><input type="submit" value="上傳"/></form></body> </html>
執行截圖:
11.5、上傳client
本例中利用javascript和HTML5?File?API來提供進度條。以報告上傳的進度。
html5.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html><head><title>My JSP 'html5.jsp' starting page</title><script type="text/javascript">var totalFileLength, totalUploaded, fileCount, filesUploaded ;window.onload = function(){document.getElementById("files").addEventListener('change', onFileSelect, false) ;document.getElementById("uploadButton").addEventListener('click', startUpload, false) ;}function onFileSelect(e){var files = e.target.files ;//FileList objectvar output = [] ;fileCount = files.length ;totalFileLength = 0 ;for( var i=0; i<fileCount; i++){var file = files[i] ;output.push(file.name, ' (', file.size, ' bytes, ',file.lastModifiedDate.toLocaleDateString(), ')');output.push("<br/>") ;debug('add ' + file.size) ;totalFileLength += file.size ;}document.getElementById("selectedFiles").innerHTML = output.join('') ;debug('totalFileLength:' + totalFileLength) ;}function debug(s){var debug = document.getElementById("debug") ;if(debug){debug.innerHTML = debug.innerHTML + '<br/>' + s ;}}function startUpload(){totalUploaded = filesUploaded = 0 ;uploadNext() ;}function uploadNext(){var xhr = new XMLHttpRequest() ;var fd = new FormData() ;var file = document.getElementById('files').files[filesUploaded] ;fd.append("fileToUpload", file) ;xhr.upload.addEventListener("progress", onUploadProgress, false) ;xhr.addEventListener("load", onUploadComplete, false) ;xhr.addEventListener("error", onUploadFailed, false) ;xhr.open("POST", "multipleUploads") ;debug("uploading " + file.name) ;xhr.send(fd) ;}function onUploadProgress(e){if(e.lengthComputable){var percentComplete = parseInt(e.loaded + totalUploaded) * 100/totalFileLength ;var bar = document.getElementById("bar") ;bar.style.width = percentComplete + "%" ;bar.innerHTML = percentComplete + " %complete" ;}else{debug("unable to compute") ;}}function onUploadComplete(e){totalUploaded += document.getElementById("files").files[filesUploaded].size ;filesUploaded ++ ;debug("complete " + filesUploaded + " of " + fileCount) ;debug("totalUploaded: " + totalUploaded) ;if(filesUploaded < fileCount){uoloadNext() ;}else{alert("Finished uploading file(s)") ;}}function onUploadFailed(e){alert("Error uploading file") ;}</script></head><body><h1>Multiple file uploads with progress bar</h1><div id="progressBar" style="height:20px;border:2px solid green"><div id="bar" style="height:100%;background:#33dd33;width:0%"></div></div><form id="form1" action="multipleUploads" enctype="multiple/form-data" method="post"><input type="file" id="files" multiple/><br/><output id="selectedFiles"></output><input id="uploadButton" type="button" value="Upload"/></form><div id="debug" style="height:100px; border:2px solid green; overflow:auto"></div></body> </html>總結
- 上一篇: linuxc线程信号-pthread_c
- 下一篇: SpringHttpInvoker解析2