javaweb開發之處理表單上傳文件和文件下載

1、基於表單的上傳文件

1. enctype屬性

當表單須要上傳文件時,需指定表單 enctype 的值爲 multipart/form-data。
在 form 元素的語法中,enctype 屬性指定將數據發送到服務器時瀏覽器使用的編碼類型。
  
enctype 屬性取值: 
application/x-www-form-urlencoded:表單 enctype 屬性的默認值。這種編碼方案使用有限的字符集,當使用了非字母和數字時,必須用」%HH」代替(H 表明十六進制數字)。對於大容量的二進制數據或包含非 ASCII 字符的文原本說,這種編碼不能知足要求。
multipart/form-data:form 設定了enctype=「multipart/form-data」屬性後,表示表單以二進制傳輸數據 。

2. Commons-fileupload 組件

Commons-fileupload 組件是 Apache 開源代碼組織用來處理表單文件上傳的一個子項目,該組件性能優異,能夠支持任意大小的文件的上傳。
Commons-fileupload 組件從 1.1 版本開始依賴 Apache 的另外一個項目:commons-io。

Commons-fileupload 組件上傳的基本原理 
FileUpload組件將頁面提交的全部元素(普通form表單域,如text和文件域file)都看做同樣的FileItem,這樣上傳頁面提交的 request請求也就是一個FileItem的有序組合,FileUpload組件能夠解析該request,並返回一個一個的FileItem。而對每個FileItem,FileUpload組件能夠判斷出它是普通form表單域仍是文件file域,從而根據不一樣的類型,採起不一樣的操做。若是是表單域,就讀出其值,若是是文件域,就保存文件到服務器硬盤上或者內存中。

3. 示例

UploadServlet.java html

package cn.heimar.upload;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
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.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * 1,限制上傳文件大小 2,限制上傳文件類型 3,設置上傳緩存大小
 */
public class UploadServlet extends HttpServlet {
    private String[] allowedSuffix = new String[] { "JPG", "JPEG", "GIF","BMP", "PNG", "ICO" };

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
        // 判斷上傳的確實是一個包含了文件域的表單
        boolean isMultipart = ServletFileUpload.isMultipartContent(req);
        if (isMultipart) {
            try {
                // 處理有文件的表單內容
                // Create a factory for disk-based file items
                DiskFileItemFactory factory = new DiskFileItemFactory();
                File folder = new File("C:\\uploadtemp");
                if(!folder.exists()){
                    folder.mkdirs();
                }
                // 設置臨時文件夾
                factory.setRepository(folder);
                // 設置緩存區大小
                factory.setSizeThreshold(3 * 1024 * 1024);

                // 建立一個上傳處理器
                ServletFileUpload upload = new ServletFileUpload(factory);

                // 設置一次請求可以上傳的文件總大小
                upload.setSizeMax(10 * 1024 * 1024);

                // 解析請求
                List<FileItem> items = upload.parseRequest(req);

                //FileItem:包裝了普通表單域和文件域的統一對象
                for (FileItem item : items) {
                    // isFormField是在判斷當前FileItem是否是普通表單域
                    if (item.isFormField()) {
                        // item.getFieldName:表單屬性名稱
                        String name = item.getFieldName();
                        // item.getString:表單屬性值
                        String value = item.getString();

                        System.out.println(name + "            " + value);
                    } else {
                        String fieldName = item.getFieldName();
                        String fileName = item.getName();
                        String contentType = item.getContentType();
                        boolean isInMemory = item.isInMemory();
                        long sizeInBytes = item.getSize();

                        // 判斷文件類型是否合法
                        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
                        if (Arrays.asList(allowedSuffix).contains(suffix.toUpperCase())) {
                            String writeFileName = UUID.randomUUID().toString();
                            String fp = this.getServletContext().getRealPath("/upload")
									+ File.separator
									+ writeFileName
									+ "."
			    						+ suffix;
                            item.write(new File(fp));
                        } else {
                            System.out.println("文件類型不合法");
                        }
                    }
                }
            } catch (SizeLimitExceededException fx) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // 按照普通表單的方法處理
        }
    }
}

upload.jsp java


<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/upload" method="POST" enctype="multipart/form-data">
<table>
	<tr>
		<td>文件名稱:</td>
		<td><input type="text" name="name" /></td>
	</tr>
	<tr>
		<td>文件:</td>
		<td><input type="file" " name="filepath"/></td>
	</tr>
	<tr>
		<td colspan="2"><input type="submit" value="上傳" /></td>
	</tr>
</table>

</form>
</body>
</html>

2、文件下載

情景:

在一些網絡系統中,須要隱藏下載文件的真實地址,或者下載的文件須要一個程序來動態的肯定後在傳送給客戶端。 apache

解決方案: 瀏覽器

利用程序編碼實現下載。
能夠增長安全訪問控制,只對通過受權認證的用戶提供下載;
能夠從任意位置提供下載的數據。

利用程序實現下載須要設置 2 個報頭: 緩存

Web 服務器須要告訴瀏覽器其所輸出的內容的類型不是普通的文本文件或 HTML 文件,而是一個要保存到本地的下載文件。設置Content-Type 的值爲:application/x-msdownload

Web 服務器但願瀏覽器不直接處理相應的實體內容,而是由用戶選擇將相應的實體內容保存到一個文件中,這須要設置 Content-Disposition 報頭。該報頭指定了接收程序處理數據內容的方式,在 HTTP 應用中只有 attachment 是標準方式,attachment 表示要求用戶干預。在 attachment 後面還能夠指定 filename 參數,該參數是服務器建議瀏覽器將實體內容保存到文件中的文件名稱。在設置 Content-Dispostion 以前必定要指定 Content-Type。 安全

示例: 服務器

DownloadServlet.java 網絡

package cn.heimar.upload;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DownloadServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String filename = req.getParameter("file");
		/*
		 * 設置響應報頭 contentType: application/x-msdownload -->
		 * 告訴瀏覽器其所輸出的內容的類型不是普通的文本文件或 HTML 文件,而是一個要保存到本地的下載文件
		 */
		// response.setHeader("content-type", "application/x-msdownload");
		resp.setContentType("application/x-msdownload");
		/*
		 * 設置響應報頭 Content-Disposition: attachment Web 服務器但願瀏覽器不直接處理相應的實體內容,
		 * 而是由用戶選擇將相應的實體內容保存到一個文件中
		 */
		resp.setHeader("Content-Disposition", "attachment; filename=11111.zip");

		String filePath = this.getServletContext().getRealPath(
				"/WEB-INF/download")
				+ File.separator + filename;
		BufferedInputStream is = new BufferedInputStream(new FileInputStream(
				filePath));
		BufferedOutputStream os = new BufferedOutputStream(
				resp.getOutputStream());

		byte[] buf = new byte[1024];
		int len = 0;

		while ((len = is.read(buf)) != -1) {
			os.write(buf, 0, len);
		}

		is.close();
		os.close();
	}

}
download.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/download?file=test.zip">點擊下載</a>
</body>
</html>
相關文章
相關標籤/搜索