文件上传和下载

 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/文件上传和下载WebContentdownload
		
		
		//将指定路径的文件绑定成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());
	}
}

  

页面显示:

    

原文地址:https://www.cnblogs.com/gshao/p/10389389.html