servlet文件上传下载_Servlet上传文件和下载文件示例

servlet文件上传下载

Servlet Upload File and Download File is a common task in java web application. Since I have written a lot about java servlet recently, I thought to provide a sample example of servlet file upload to server and then download from server to client.

Servlet上载文件和下载文件是Java Web应用程序中的常见任务。 由于最近我写了很多有关Java servlet的文章 ,因此我想提供一个示例示例,该示例将servlet文件上传到服务器,然后从服务器下载到客户端。

Servlet上传文件 (Servlet Upload File)

Our use case is to provide a simple HTML page where client can select a local file to be uploaded to server. On submission of request to upload the file, our servlet program will upload the file into a directory in the server and then provide the URL through which user can download the file. For security reason, user will not be provided direct URL for downloading the file, rather they will be given a link to download the file and our servlet will process the request and send the file to user.

我们的用例是提供一个简单HTML页面,客户端可以在其中选择要上传到服务器的本地文件。 在提交上传文件的请求后,我们的Servlet程序会将文件上传到服务器中的目录中,然后提供URL,用户可以通过该URL下载文件。 出于安全原因,不会为用户提供下载文件的直接URL,而是会为他们提供下载文件的链接,并且我们的Servlet将处理请求并将文件发送给用户。

We will create a dynamic web project in Eclipse and the project structure will look like below image.

我们将在Eclipse中创建一个动态Web项目,项目结构如下图所示。

Let’s look into all the components of our web application and understand the implementation.

让我们研究一下Web应用程序的所有组件并了解实现。

Java将文件上传到服务器HTML页面 (HTML Page for Java Uploading File to Server)

We can upload a file to server by sending a post request to servlet and submitting the form. We can’t use GET method for uploading file.

我们可以通过向Servlet发送发布请求并提交表单来将文件上传到服务器。 我们无法使用GET方法上传文件。

Another point to note is that enctype of form should be multipart/form-data.

还要注意的一点是,表单的enctype应该是multipart / form-data

To select a file from user file system, we need to use input element with type as file.

要从用户文件系统中选择文件,我们需要使用类型file的 输入元素。

So we can have a simple HTML page index.html for uploading file as:

因此,我们可以使用一个简单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>

用于文件上传的服务器文件位置 (Server File Location for File Upload)

We need to store file into some directory at server, we can have this directory hardcoded in program but for better flexibility, we will keep it configurable in deployment descriptor context params. Also we will add our upload file html page to the welcome file list.

我们需要将文件存储到服务器上的某个目录中,我们可以在程序中对这个目录进行硬编码,但是为了获得更好的灵活性,我们将在部署描述符上下文参数中将其保持可配置状态。 另外,我们会将上传文件的html页面添加到欢迎文件列表中。

Our web.xml file will look like below:

我们的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用于文件上传位置 (ServletContextListener for File Upload Location)

Since we need to read context parameter for file location and create a File object from it, we can write a ServletContextListener to do it when context is initialized. We can set absolute directory location and File object as context attribute to be used by other servlets.

由于我们需要读取文件位置的上下文参数并从中创建File对象,因此可以在初始化上下文时编写ServletContextListener来执行此操作。 我们可以将绝对目录位置和File对象设置为上下文属性,以供其他servlet使用。

Our ServletContextListener implementation code is like below.

我们的ServletContextListener实现代码如下。

package com.journaldev.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 (File Upload Download Servlet)

Update: Servlet Specs 3 added support to upload files on server in the API, so we won’t need to use any third party API. Please check out Servlet 3 Upload File.

更新 :Servlet Specs 3添加了在API中将文件上传到服务器上的支持,因此我们不需要使用任何第三方API。 请检出Servlet 3上传文件

For File upload, we will use Apache Commons FileUpload utility, for our project we are using version 1.3, FileUpload depends on Apache Commons IO jar, so we need to place both in the lib directory of the project, as you can see that in above image for project structure.

对于文件上传,我们将使用Apache Commons FileUpload实用程序,对于我们的项目,我们使用版本1.3,FileUpload依赖于Apache Commons IO jar,因此我们需要将两者都放置在项目的lib目录中,如您在上面看到的那样项目结构的图像。

We will use DiskFileItemFactory factory that provides a method to parse the HttpServletRequest object and return list of FileItem. FileItem provides useful method to get the file name, field name in form, size and content type details of the file that needs to be uploaded. To write file to a directory, all we need to do it create a File object and pass it as argument to FileItem write() method.

我们将使用DiskFileItemFactory工厂,该工厂提供一种方法来解析HttpServletRequest对象并返回FileItem的列表。 FileItem提供了有用的方法来获取文件名,字段名,格式,大小和需要上载的文件的内容类型的详细信息。 要将文件写入目录,我们要做的就是创建一个File对象,并将其作为参数传递给FileItem write()方法。

Since the whole purpose of the servlet is to upload file, we will override init() method to initialise the DiskFileItemFactory object instance of the servlet. We will use this object in the doPost() method implementation to upload file to server directory.

由于Servlet的全部目的是上传文件,因此我们将覆盖init()方法以初始化Servlet的DiskFileItemFactory对象实例。 我们将在doPost()方法实现中使用此对象将文件上传到服务器目录。

Once the file gets uploaded successfully, we will send response to client with URL to download the file, since HTML links use GET method,we will append the parameter for file name in the URL and we can utilise the same servlet doGet() method to implement file download process.

成功上传文件后,我们将使用URL向客户端发送响应以下载文件,因为HTML链接使用GET方法,因此我们将在URL中添加文件名参数,并且可以使用相同的servlet doGet()方法实施文件下载过程。

For implementing download file servlet, first we will open the InputStream for the file and use ServletContext.getMimeType() method to get the MIME type of the file and set it as response content type.

为了实现下载文件servlet,首先,我们将打开文件的InputStream并使用ServletContext.getMimeType()方法获取文件的MIME类型并将其设置为响应内容类型。

We will also need to set the response content length as length of the file. To make sure that client understand that we are sending file in response, we need to set “Content-Disposition” header with value as “attachment; filename=”fileName”.

我们还需要将响应内容的长度设置为文件的长度。 为了确保客户端了解我们正在发送文件作为响应,我们需要将“ Content-Disposition ”标头的值设置为“ attachment”; filename =“ fileName”

Once we are done with setting response configuration, we can read file content from InputStream and write it to ServletOutputStream and the flush the output to client.

完成设置响应配置后,我们可以从InputStream读取文件内容并将其写入ServletOutputStream并将输出刷新到客户端。

Our final implementation of UploadDownloadFileServlet servlet looks like below.

我们的UploadDownloadFileServlet Servlet的最终实现如下所示。

package com.journaldev.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>");
	}

}

The sample execution of the project is shown in below images.

下图显示了该项目的示例执行。

下载Servlet文件上传下载项目 (Download Servlet File Upload Download Project)

You can download Apache Commons IO jar and Apache Commons FileUpload jar from below URLs.

您可以从以下网址下载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

https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi
https://commons.apache.org/proper/commons-io/download_io.cgi

Check out next article in the series about Servlet Exception Handling.

查阅有关Servlet异常处理系列的下一篇文章。

翻译自: https://www.journaldev.com/1964/servlet-upload-file-download-example

servlet文件上传下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Servlet文件上传功能可以通过使用注解@MultipartConfig将Servlet标识为支持文件上传,然后将multipart/form-data的POST请求封装成Part对象,通过Part对象对上传的文件进行操作。以下是一个文件上传Servlet示例代码: ```java @WebServlet("/uploadServlet") @MultipartConfig // 如果是文件上传,必须要设置该注解! public class UploadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("文件上传..."); // 设置请求的编码格式 req.setCharacterEncoding("UTF-8"); // 获取普通表单项(获取参数) String uname = req.getParameter("uname"); // 表单中表单元素的name属性值 System.out.println("uname: " + uname); // 获取Part对象(Servlet将multipart/form-data的POST请求封装成Part对象) Part part = req.getPart("myfile"); // 通过Part对象得到上传的文件名 String fileName = part.getSubmittedFileName(); System.out.println("上传文件名:" + fileName); // 得到文件存放的路径 String filePath = req.getServletContext().getRealPath("/"); System.out.println("文件存放路径:" + filePath); // 上传文件到指定目录 part.write(filePath + "/" + fileName); } } ``` 而文件下载功能可以通过设置download属性来实现。以下是一个文件下载的JSP页面的示例代码: ```html <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>文件下载</title> </head> <body> <!-- 浏览器能够识别的资源 --> <a href="download/hello.txt">文本文件</a> <a href="download/pic.jpg">图片文件</a> <!-- 浏览器不能够识别的资源 --> <a href="download/zzz.rar">压缩文件</a> <hr> <a href="download/hello.txt" download>文本文件</a> <a href="download/pic.jpg" download="test.png">图片文件</a> <hr> <form action="downloadServlet"> 文件名:<input type="text" name="fileName" placeholder="请输入要下载文件名"> <button>下载</button> </form> </body> </html> ``` 以上是文件上传下载的实现方法,你可以根据需要进行调整和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值