Servlet上传文件和下载文件示例
Servlet上载文件和下载文件是Java Web应用程序中的常见任务。
由于最近我写了很多有关Java servlet的文章,因此我想提供一个示例示例,该示例将servlet文件上传到服务器,然后从服务器下载到客户端。
Servlet上传文件
我们的用例是提供一个简单HTML页面,客户端可以其中选择要上传到服务器的本地文件。
在提交上传文件的请求时,我们的Servlet程序会将文件上传到服务器中的目录中,然后提供URL,用户可以通过该URL下载文件。
出于安全原因,不会为用户提供下载文件的直接URL,而是会为他们提供下载文件的链接,并且我们的Servlet将处理请求并将文件发送给用户。
我们将在Eclipse中创建一个动态Web项目,项目结构如下图所示。
让我们研究一下Web应用程序的所有组件并了解其实现。
Java将文件上传到服务器HTML页面
我们可以通过向Servlet发送发布请求并提交表单来将文件上传到服务器。
我们无法使用GET方法上传文件。
还要注意的一点是,表单的enctype应该是multipart/form-data。
要从用户文件系统中选择文件,我们需要使用类型为文件的输入元素。
因此,我们可以使用一个简单HTML页面index.html将文件上传为:
<html> <head></head> <body> <form action="UploadDownloadFileServlet" method="post" enctype="multipart/form-data"> Select File to Upload:<input type="file" name="fileName"> <br> <input type="submit" value="Upload"> </form> </body> </html>
用于文件上传的服务器文件位置
我们需要将文件存储到服务器上的某个目录中,我们可以在程序中对这个目录进行硬编码,但是为了获得更好的灵活性,我们将使其在部署描述符上下文参数中可配置。
另外,我们会将上传文件HTML页面添加到欢迎文件列表中。
我们的web.xml文件如下所示:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>ServletFileUploadDownloadExample</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <context-param> <param-name>tempfile.dir</param-name> <param-value>tmpfiles</param-value> </context-param> </web-app>
ServletContextListener用于文件上传位置
由于我们需要读取文件位置的上下文参数并从中创建File对象,因此可以在初始化上下文时编写ServletContextListener来执行此操作。
我们可以将绝对目录位置和File对象设置为上下文属性,以供其他servlet使用。
我们的ServletContextListener实现代码如下。
package com.theitroad.servlet; import java.io.File; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class FileLocationContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent servletContextEvent) { String rootPath = System.getProperty("catalina.home"); ServletContext ctx = servletContextEvent.getServletContext(); String relativePath = ctx.getInitParameter("tempfile.dir"); File file = new File(rootPath + File.separator + relativePath); if(!file.exists()) file.mkdirs(); System.out.println("File Directory created to be used for storing files"); ctx.setAttribute("FILES_DIR_FILE", file); ctx.setAttribute("FILES_DIR", rootPath + File.separator + relativePath); } public void contextDestroyed(ServletContextEvent servletContextEvent) { //do cleanup if needed } }
文件上传下载Servlet
更新:Servlet Specs 3添加了对在API中的服务器上上传文件的支持,因此我们不需要使用任何第三方API。
请检出Servlet 3上传文件。
对于文件上传,我们将使用Apache Commons FileUpload实用程序,对于我们的项目,我们使用版本1.3,FileUpload依赖于Apache Commons IO jar,因此我们需要将二者都放置在项目的lib目录中,如您在上面看到的那样项目结构的图像。
我们将使用DiskFileItemFactory工厂,该工厂提供一种解析HttpServletRequest对象并返回FileItem列表的方法。
FileItem提供了有用的方法来获取文件名,字段名,格式,大小和需要上载的文件的内容类型的详细信息。
要将文件写入目录,我们要做的就是创建一个File对象,并将其作为参数传递给FileItem write()方法。
由于Servlet的全部目的是上传文件,因此我们将覆盖init()方法以初始化Servlet的" DiskFileItemFactory"对象实例。
我们将在doPost()方法实现中使用此对象将文件上传到服务器目录。
成功上传文件后,我们将使用URL向客户端发送响应以下载文件,因为HTML链接使用GET方法,因此我们将在URL中添加文件名参数,并且可以使用相同的servlet doGet()方法实施文件下载过程。
为了实现下载文件servlet,首先,我们将打开文件的InputStream并使用ServletContext.getMimeType()方法获取文件的MIME类型并将其设置为响应内容类型。
我们还需要将响应内容的长度设置为文件的长度。
为了确保客户端理解我们正在发送文件作为响应,我们需要将" Content-Disposition"标头设置为" attachment"; filename =" fileName"。
设置好响应配置后,就可以从InputStream读取文件内容并将其写入ServletOutputStream并将输出刷新到客户端。
我们的UploadDownloadFileServlet servlet的最终实现如下所示。
package com.theitroad.servlet; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; 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.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; @WebServlet("/UploadDownloadFileServlet") public class UploadDownloadFileServlet extends HttpServlet { private static final long serialVersionUID = 1L; private ServletFileUpload uploader = null; @Override public void init() throws ServletException{ DiskFileItemFactory fileFactory = new DiskFileItemFactory(); File filesDir = (File) getServletContext().getAttribute("FILES_DIR_FILE"); fileFactory.setRepository(filesDir); this.uploader = new ServletFileUpload(fileFactory); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String fileName = request.getParameter("fileName"); if(fileName == null || fileName.equals("")){ throw new ServletException("File Name can't be null or empty"); } File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileName); if(!file.exists()){ throw new ServletException("File doesn't exists on server."); } System.out.println("File location on server::"+file.getAbsolutePath()); ServletContext ctx = getServletContext(); InputStream fis = new FileInputStream(file); String mimeType = ctx.getMimeType(file.getAbsolutePath()); response.setContentType(mimeType != null? mimeType:"application/octet-stream"); response.setContentLength((int) file.length()); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); ServletOutputStream os = response.getOutputStream(); byte[] bufferData = new byte[1024]; int read=0; while((read = fis.read(bufferData))!= -1){ os.write(bufferData, 0, read); } os.flush(); os.close(); fis.close(); System.out.println("File downloaded at client successfully"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if(!ServletFileUpload.isMultipartContent(request)){ throw new ServletException("Content type is not multipart/form-data"); } response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.write("<html><head></head><body>"); try { List<FileItem> fileItemsList = uploader.parseRequest(request); Iterator<FileItem> fileItemsIterator = fileItemsList.iterator(); while(fileItemsIterator.hasNext()){ FileItem fileItem = fileItemsIterator.next(); System.out.println("FieldName="+fileItem.getFieldName()); System.out.println("FileName="+fileItem.getName()); System.out.println("ContentType="+fileItem.getContentType()); System.out.println("Size in bytes="+fileItem.getSize()); File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileItem.getName()); System.out.println("Absolute Path at server="+file.getAbsolutePath()); fileItem.write(file); out.write("File "+fileItem.getName()+ " uploaded successfully."); out.write("<br>"); out.write("<a href=\"UploadDownloadFileServlet?fileName="+fileItem.getName()+"\">Download "+fileItem.getName()+"</a>"); } } catch (FileUploadException e) { out.write("Exception in uploading file."); } catch (Exception e) { out.write("Exception in uploading file."); } out.write("</body></html>"); } }
下载Servlet文件上传下载项目
您可以从以下网址下载Apache Commons IO jar和Apache Commons FileUpload jar。
https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi
https://commons.apache.org/proper/commons-io/download_io.cgi