第十章_文件上传

简介:

10.1、客户端编程

要上传文件,必须利用multipart/form-data设置HTML表单的enctype的属性值,像下面这样:

[html]  view plain  copy
 print ?
  1. <form action="action" enctype="multipart/form-data" method="post">  
  2.         Select a file<input type="file" name="fieldName" />  
  3.         <input type="submit" value="Upload" />  
  4.     </form>  

10.2、服务器端编程

Servlet中的服务器端文件上传编程主要围绕着MultipartConfig注解类型和javax.servlet.http.Part接口进行。

处理上传文件的Servlet必须用@MultipartConfig进行标注。MultipartConfig可以带有以下属性,这些都是可选的。

maxFileSize,表示最多可上传的文件容量。超过设定值的文件将会遭到拒绝。默认值为-1,表示不受限制。

maxRequestSize,表示允许多部分HTTP请求的最大容量。它的默认值为-1,不受限制。

Location,上传的文件保存到磁盘的指定位置,调用Part中的write方法将用到它。

fileSizeThreshold,设定一个溢出尺寸,超过这个值之后,上传的文件将被写入磁盘。

在一个由多部分组成的请求中,每一个表单域,包括非文件域,都会被转换成一个PartHttpServletRequest接口定义了以下方法来处理多部分的请求:

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” 

例如,上传输入域中一个名称documentnote.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

[html]  view plain  copy
 print ?
  1. package app11a.servlet;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5.   
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.annotation.MultipartConfig;  
  8. import javax.servlet.annotation.WebServlet;  
  9. import javax.servlet.http.HttpServlet;  
  10. import javax.servlet.http.HttpServletRequest;  
  11. import javax.servlet.http.HttpServletResponse;  
  12. import javax.servlet.http.Part;  
  13. @WebServlet(urlPatterns = {"/singleUpload"})  
  14. @MultipartConfig  
  15. public class SingleUploadServlet extends HttpServlet{  
  16.     private static final long serialVersionUID = 1L;  
  17.     /**  
  18.      * 通过part过得文件名称  
  19.      * @param part  
  20.      * @return  
  21.      */  
  22.     private String getFileName(Part part){  
  23.         String contentDispositionHeader = part.getHeader("content-disposition") ;  
  24.         String[] elements = contentDispositionHeader.split(";") ;  
  25.         for(String element: elements){  
  26.             if(element.trim().startsWith("filename")){  
  27.                 return element.substring(element.indexOf('=') + 1).trim().replace("\"", "") ;  
  28.             }  
  29.         }  
  30.         return null ;  
  31.     }  
  32.     @Override  
  33.     public void doPost(HttpServletRequest req, HttpServletResponse resp)  
  34.             throws ServletException, IOException {  
  35.         req.setCharacterEncoding("utf-8") ;  
  36.         resp.setCharacterEncoding("utf-8") ;  
  37.         Part part = req.getPart("filename") ;  
  38.         String fileName = getFileName(part) ;  
  39.         if(fileName != null && !fileName.isEmpty()){  
  40.             part.write(getServletContext().getRealPath("/WEB-INF") + "/" + fileName) ;  
  41.         }  
  42.         resp.setContentType("text/html") ;  
  43.         PrintWriter writer = resp.getWriter() ;  
  44.         writer.print("<br/>Upload file name: " + fileName) ;  
  45.         writer.print("<br/>Size: " + part.getSize()) ;  
  46.         String author = req.getParameter("author") ;  
  47.         writer.print("<br/>Author: " + author) ;  
  48.     }  
  49.       
  50. }  

singleUplpad.jsp

[html]  view plain  copy
 print ?
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <html>  
  3.   <head>  
  4.     <title>My JSP 'singleUpload.jsp' starting page</title>  
  5.   </head>  
  6.     
  7.   <body>  
  8.     <h1>Select a file to upload</h1>  
  9.     <form action="singleUpload" method="post" enctype="multipart/form-data">  
  10.         Author: <input type="text" name="author"/><br/>  
  11.         Select file to upload <input type="file" name="filename"/><br/>  
  12.         <input type="submit" value="上传"/>  
  13.     </form>  
  14.   </body>  
  15. </html>  



11.4、多文件上传

MultipleUploadsServlet.java

[html]  view plain  copy
 print ?
  1. package app11a.servlet;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5. import java.util.Collection;  
  6.   
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.annotation.MultipartConfig;  
  9. import javax.servlet.annotation.WebServlet;  
  10. import javax.servlet.http.HttpServlet;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13. import javax.servlet.http.Part;  
  14. @WebServlet(urlPatterns = {"/multipleUploads"})  
  15. @MultipartConfig  
  16. public class MultipleUploadsServlet extends HttpServlet{  
  17.       
  18.     private static final long serialVersionUID = 1L;  
  19.       
  20.     private String getFileName(Part part){  
  21.         String contentDispositionHeader = part.getHeader("content-disposition") ;  
  22.         String[] elements = contentDispositionHeader.split(";") ;  
  23.         for(String element: elements){  
  24.             if(element.trim().startsWith("filename")){  
  25.                 return element.substring(element.indexOf('=') + 1).trim().replace("\"", "") ;  
  26.             }  
  27.         }  
  28.         return null ;  
  29.     }  
  30.       
  31.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  32.         throws ServletException, IOException{  
  33.         request.setCharacterEncoding("utf-8") ;  
  34.         response.setCharacterEncoding("utf-8") ;  
  35.         response.setContentType("text/html") ;  
  36.         PrintWriter writer = response.getWriter() ;  
  37.           
  38.         Collection<Part> parts = request.getParts() ;  
  39.         for(Part part : parts){  
  40.             //通过getContentType获得是否是文件域  
  41.             if(part.getContentType() != null){  
  42.                 String fileName = getFileName(part) ;  
  43.                 //通过文件名获得是否有文件  
  44.                 if(fileName != null && ! fileName.isEmpty()){  
  45.                     part.write(getServletContext().getRealPath("/WEB-INF") + "/" + fileName) ;  
  46.                     writer.print("<br/>Uploaded file name: " + fileName) ;  
  47.                     writer.print("<br/>Size: " + part.getSize()) ;  
  48.                 }  
  49.             }else{  
  50.                 String partName = part.getName() ;  
  51.                 String fieldValue = request.getParameter(partName) ;  
  52.                 writer.print("<br/>" + partName + ": " + fieldValue) ;  
  53.             }  
  54.         }  
  55.     }  
  56.       
  57. }  

multipleUploads.jsp

[html]  view plain  copy
 print ?
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <html>  
  3.   <head>  
  4.     <title>My JSP 'multipleUploads.jsp' starting page</title>  
  5.   </head>  
  6.     
  7.   <body>  
  8.     <h1>Select a file to upload</h1>  
  9.     <form action="multipleUploads" enctype="multipart/form-data" method="post">  
  10.         Author: <input name="author"/><br/>  
  11.         First file to upload <input type="file" name="uploadFile"/>  
  12.         <br/>  
  13.         Second file to upload <input type="file" name="uploadFile2"/>  
  14.         <br/>  
  15.         <input type="submit" value="上传"/>  
  16.     </form>  
  17.   </body>  
  18. </html>  

运行截图:



11.5、上传客户端

本例中利用JavaScriptHTML5 File API来提供进度条,以报告上传的进度。

html5.jsp

[html]  view plain  copy
 print ?
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <html>  
  3.   <head>  
  4.     <title>My JSP 'html5.jsp' starting page</title>  
  5.     <script type="text/javascript">  
  6.         var totalFileLength, totalUploaded, fileCount, filesUploaded ;  
  7.         window.onload = function(){  
  8.             document.getElementById("files").addEventListener('change', onFileSelect, false) ;  
  9.             document.getElementById("uploadButton").addEventListener('click', startUpload, false) ;  
  10.         }  
  11.         function onFileSelect(e){  
  12.             var files = e.target.files ;//FileList object  
  13.             var output = [] ;  
  14.             fileCount = files.length ;  
  15.             totalFileLength = 0 ;  
  16.             for( var i=0; i<fileCount; i++){  
  17.                 var file = files[i] ;  
  18.                 output.push(file.name, ' (', file.size, ' bytes, ',  
  19.                     file.lastModifiedDate.toLocaleDateString(), ')');  
  20.                 output.push("<br/>") ;  
  21.                 debug('add ' + file.size) ;  
  22.                 totalFileLength += file.size ;  
  23.             }  
  24.             document.getElementById("selectedFiles").innerHTML = output.join('') ;  
  25.             debug('totalFileLength:' + totalFileLength) ;  
  26.         }  
  27.         function debug(s){  
  28.             var debug = document.getElementById("debug") ;  
  29.             if(debug){  
  30.                 debug.innerHTML = debug.innerHTML + '<br/>' + s ;  
  31.             }  
  32.         }  
  33.         function startUpload(){  
  34.             totalUploaded = filesUploaded = 0 ;  
  35.             uploadNext() ;  
  36.         }  
  37.         function uploadNext(){  
  38.             var xhr = new XMLHttpRequest() ;  
  39.             var fd = new FormData() ;  
  40.             var file = document.getElementById('files').files[filesUploaded] ;  
  41.             fd.append("fileToUpload", file) ;  
  42.             xhr.upload.addEventListener("progress", onUploadProgress, false) ;  
  43.             xhr.addEventListener("load", onUploadComplete, false) ;  
  44.             xhr.addEventListener("error", onUploadFailed, false) ;  
  45.             xhr.open("POST", "multipleUploads") ;  
  46.             debug("uploading " + file.name) ;  
  47.             xhr.send(fd) ;  
  48.         }  
  49.         function onUploadProgress(e){  
  50.             if(e.lengthComputable){  
  51.                 var percentComplete = parseInt(e.loaded + totalUploaded) * 100/totalFileLength ;  
  52.                 var bar = document.getElementById("bar") ;  
  53.                 bar.style.width = percentComplete + "%" ;  
  54.                 bar.innerHTML = percentComplete + " %complete" ;  
  55.             }else{  
  56.                 debug("unable to compute") ;  
  57.             }  
  58.         }  
  59.         function onUploadComplete(e){  
  60.             totalUploaded += document.getElementById("files").files[filesUploaded].size ;  
  61.             filesUploaded ++ ;  
  62.             debug("complete " + filesUploaded + " of " + fileCount) ;  
  63.             debug("totalUploaded: " + totalUploaded) ;  
  64.             if(filesUploaded < fileCount){  
  65.                 uoloadNext() ;  
  66.             }else{  
  67.                 alert("Finished uploading file(s)") ;  
  68.             }  
  69.         }  
  70.         function onUploadFailed(e){  
  71.             alert("Error uploading file") ;  
  72.         }  
  73.     </script>  
  74.   </head>  
  75.     
  76.   <body>  
  77.     <h1>Multiple file uploads with progress bar</h1>  
  78.     <div id="progressBar" style="height:20px;border:2px solid green">  
  79.         <div id="bar" style="height:100%;background:#33dd33;width:0%">  
  80.         </div>  
  81.     </div>  
  82.     <form id="form1" action="multipleUploads" enctype="multiple/form-data" method="post">  
  83.         <input type="file" id="files" multiple/>  
  84.         <br/>  
  85.         <output id="selectedFiles"></output>  
  86.         <input id="uploadButton" type="button" value="Upload"/>  
  87.     </form>  
  88.     <div id="debug" style="height:100px; border:2px solid green; overflow:auto"></div>  
  89.   </body>  
  90. </html>  
目录
相关文章
|
6月前
|
前端开发 Java Spring
教会你怎么使用SpringMVC 文件上传
教会你怎么使用SpringMVC 文件上传
73 0
|
30天前
|
前端开发 JavaScript
💥【exceljs】纯前端如何实现Excel导出下载和上传解析?
本文介绍了用于处理Excel文件的库——ExcelJS,相较于SheetJS,ExcelJS支持更高级的样式自定义且易于使用。表格对比显示,ExcelJS在样式设置、内存效率及流式操作方面更具优势。主要适用于Node.js环境,也支持浏览器端使用。文中详细展示了如何利用ExcelJS实现前端的Excel导出下载和上传解析功能,并提供了示例代码。此外,还提供了在线调试的仓库链接和运行命令,方便读者实践。
244 5
|
30天前
|
JavaScript 前端开发 编译器
吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
【10月更文挑战第2天】吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
42 2
视频文件上传接口上传不了,怎样解决??
视频文件上传接口上传不了,怎样解决??
|
6月前
|
JSON Rust 前端开发
【sheetjs】纯前端如何实现Excel导出下载和上传解析?
本文介绍了如何使用`sheetjs`的`xlsx`库在前端实现Excel的导出和上传。项目依赖包括Vite、React、SheetJS和Arco-Design。对于导出,从后端获取JSON数据,通过`json_to_sheet`、`book_new`和`writeFile`函数生成并下载Excel文件。对于上传,使用`read`函数将上传的Excel文件解析为JSON并发送至后端。完整代码示例可在GitHub仓库[fullee/sheetjs-demo](https://github.com/fullee/sheetjs-demo)中查看。
394 10
|
前端开发
前端常规关于网页文件下载的问题
前端常规关于网页文件下载的问题
63 0
|
6月前
|
前端开发 安全 应用服务中间件
Axure9官网网页的源代码篡改,自定义为个人开发使用
Axure9官网网页的源代码篡改,自定义为个人开发使用
|
6月前
|
JavaScript 前端开发 Java
今年十八,喜欢文件上传
今年十八,喜欢文件上传
52 1
|
6月前
|
JSON 前端开发 JavaScript
前端上传文件前检测文件数据🔍
前端上传文件前检测文件数据🔍
121 0
|
数据库
对象管理器设计-ConnectionManager 文件上传题 1. 对象管理器设计
对象管理器设计-ConnectionManager 文件上传题 1. 对象管理器设计