文件上傳和下載

 1. 文件上傳

瀏覽器在上傳的過程中是將文件以 二進制的流  的形式提交到服務器端.

 

1 準備一個form表單,裏面有一個上傳,form表單的類型必需是multipart/form-data

2 準備一個上傳的Servlet,到後臺接收傳過來的普通表單數據 與 文件(二進制)

3 導入相應的FileUpload jar(commons-fileupload-1.2.2.jar ,commons-io-1.4.jar)

 

重要:上傳時,我們表單的請求類型必需設置成multipart/form-data   . 上傳的method必需是POST

完成文件上傳重要方法:fileItem.write(File file);

FileItemd對象就是從request中獲得數據對象,通過調用它的write把其中的數據寫入到磁盤文件(File file

常見問題及其解決方案:

  1. 上傳文件對象封裝----CFile對象 ,可以解決 多個文件上傳 及其對應屬性的屬性很多問題。

  2. FileUtil.java 工具類   雖然可以完成上傳   但是 拿不到普通表單字段值文件上傳後,我們拿到不到上傳的文件的數據。

    解決辦法:準備兩個容器(就是集合),然後一個容器裝普通表單,另一個容器裝上傳的文件數據。把這個容器交給工具類,工具類拿到相應的數據後將數據放回到容器中。

 

 

 

 

1. 項目整體架構:

 

2. register.jsp代碼

<body>
	<form action="UploadServlet" method="post" enctype="multipart/form-data">
		用戶名:<input type="text" name="username"/><br>
		密碼:<input type="password" name="password"/><br>
		頭像1:<input type="file" name="headImg1"/><br>
		頭像2:<input type="file" name="headImg2"/><br>
		<input type="submit" value="提交"/>
	</form>
</body>

  

3. UploadServlet.java代碼

package com.gs.controller;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import com.gs.domain.CFile;
import com.gs.tools.FileUtil;

@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {                 
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			Map<String, String> fieldMap = new HashMap();
			Map<String,CFile> filesMap = new HashMap();
			FileUtil.upload(request, fieldMap, filesMap);
			//拿數據
			System.out.println(fieldMap);
			System.out.println(filesMap);
		} catch (Exception e) {
			request.setAttribute("message","類型不匹配");
			request.getRequestDispatcher("register.jsp").forward(request, response);
		}
	}
}

  

4. CFile.java代碼

package com.gs.domain;

public class CFile {
	private String filename;
	private String filepath;
	public String getFilename() {
		return filename;
	}
	public void setFilename(String filename) {
		this.filename = filename;
	}
	public String getFilepath() {
		return filepath;
	}
	public void setFilepath(String filepath) {
		this.filepath = filepath;
	}
	@Override
	public String toString() {
		return "CFile [filename=" + filename + ", filepath=" + filepath + "]";
	}
}

  

5. FileUtil.java 工具類代碼

package com.gs.tools;

import java.io.File;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

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;
import org.apache.commons.io.FilenameUtils;

import com.gs.domain.CFile;

public class FileUtil {
	//準備只支持的圖片類型
	private static final String[] IMG_TYPE = {"jpg","png","gif","bmp"};
	public static void upload(HttpServletRequest request, Map<String,String> fieldMap,
			Map<String,CFile> filesMap) {
		//判斷是否有一個文件上傳的請求
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		if(isMultipart){
			//爲基於磁盤的文件項創建工廠,並創建一個新的文件上傳對象
			DiskFileItemFactory  factory = new DiskFileItemFactory();
			ServletFileUpload upload = new ServletFileUpload(factory);
			upload.setFileSizeMax(1024*1024*2);//單個文件最大2M
			upload.setSizeMax(1024*1024*5); //所有文件的請求的大小 5M
			
			try {
				//拿到每一項表單控件組成的 FileItem類型的集合
				List<FileItem> items = upload.parseRequest(request);
				for (FileItem fileItem : items) {
					System.out.println(fileItem);
					//如果是一般表單,用一般表單的處理方式
					if(fileItem.isFormField()) {
						//表單控件name的名稱
						String filedName = fileItem.getFieldName();
						//表單控件name名稱對應的值
						String value = fileItem.getString("UTF-8");
						//value = new String(value.getBytes("ISO-8859-1"),"utf-8");//也可以解決亂碼問題
						fieldMap.put(filedName, value);//將鍵值對添加到集合內
					}else{//如果是文件上傳的控件
						//獲取文件名,使用工具類:FilenameUtils解決ie瀏覽器拿文件全路徑名的問題
						String name = FilenameUtils.getName(fileItem.getName());
						//獲取後綴名
						String ext = FilenameUtils.getExtension(name);
						
						//驗證後綴名是否滿足圖片類型
						if(Arrays.asList(IMG_TYPE).contains(ext)) {
							String randomUUID = UUID.randomUUID().toString();
						
							//(通過upload文件夾)獲取項目下的存儲資源的路徑
							// F:\workspace\.metadata\...\文件上傳\\upload
							String path = request.getServletContext().getRealPath("/upload");
							path = path.substring(0, path.indexOf(".metadata"));
	
							String pa = request.getContextPath(); //項目的上下文路徑,這裏獲取的是亂碼
							pa = URLDecoder.decode(pa,"utf-8");//解碼
							System.out.println(pa);
							
							path=path.replace('/', '\\')+pa+"\\WebContent\\upload";
							System.out.println(path);
				
							//創建文件對象
							File file = new File(path, randomUUID+"."+ext);
							//將二進制流寫入文件對象中
							fileItem.write(file);
							
							CFile cfile = new CFile();
							cfile.setFilename(randomUUID+"."+ext);
							cfile.setFilepath(file.getAbsolutePath());
							filesMap.put(randomUUID+"."+ext,cfile);
						}else {
							throw new RuntimeException("文件類型不符合");
						}
					}
				}
			}catch (RuntimeException e) {
				throw e;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

  

 

2. 文件下載

文件下載可以有兩種方法:

    1.  超連接直接下載功能 

    2. 使用java代碼經過servlet來進行下載

 

1. download.jsp代碼

<body>
	<p style="color:red"> 超連接直接下載功能 </p>
	<a href="download/俄羅斯方塊.html" download="俄羅斯方塊">俄羅斯方塊.html</a><br />
	<a href="download/金玟岐 - 歲月神偷.mp3" download="歲月神偷">金玟岐 - 歲月神偷.mp3</a><br />
	<a href="download/fun.mp4" download="fun視頻">fun.mp4</a><br />
	<a href="download/2.jpg" download="二次元圖片">2.jpg</a><br />
	
	<p style="color:red"> 使用java代碼經過servlet來進行下載 </p>
	<a href="DownloadServlet?filename=俄羅斯方塊.html">俄羅斯方塊.html</a><br />
	<a href="DownloadServlet?filename=金玟岐 - 歲月神偷.mp3">金玟岐 - 歲月神偷.mp3</a><br />
	<a href="DownloadServlet?filename=fun.mp4">fun.mp4</a><br />
	<a href="DownloadServlet?filename=2.jpg">2.jpg</a><br />
</body>

  

2. DownloadServlet.java代碼

package com.gs.controller;

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;

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

@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String pa = request.getContextPath(); //項目的上下文路徑,這裏獲取的是亂碼
		pa = URLDecoder.decode(pa,"utf-8");//解碼
		
		String filename = request.getParameter("filename");
		String path = request.getServletContext().getRealPath("/download");
		path = path.substring(0, path.indexOf(".metadata"));
		System.out.println(path); //F:\workspace\
		
		path=path.replace('/', '\\')+pa+"\\WebContent\\download";
		System.out.println(path); //F:\workspace\/文件上傳和下載\WebContent\download
		
		
		//將指定路徑的文件綁定成File對象
		File file = new File(path,filename);
		//設置瀏覽器不能直接打開文件
		response.setContentType("application/x-msdownload");
		
		//解決瀏覽器下載文件沒有後綴名和文件名問題
		String userAgent = request.getHeader("User-Agent");
		if(userAgent.contains("MSIE")) {
			//IE瀏覽器
			filename = URLEncoder.encode(filename,"UTF-8");
		}else {
			//其他瀏覽器
			filename = new String(filename.getBytes("UTF-8"),"ISO-8859-1");
		}
		
		response.setHeader("Content-Disposition","attachment;filename="+filename);
		//將文件以流的形式輸出到頁面中下載
		Files.copy(Paths.get(file.getAbsolutePath()), response.getOutputStream());
	}
}

  

頁面顯示:

 

    

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章