文件的上传和下载

文件的上传和下载

1.1文件的上传

文件上传主要分成两个步骤:

  • 用户在页面中选择要上传的文件,然后将请求提交到Servlet
  • Servlet收到请求,解析用户上传的文件,然后将文件存储到服务器

1.2准备工作

表单:

  • 表单的method属性必须为post
  • 表单的enctype属性必须为multipart/form-data
  • 上传文件的控件是input,type属性为file

导包:

  • commons-fileupload.jar
  • commons-io.jar

例如:

①创建一个form表单

<form action="/*指定一个servlet*/" method="post" enctype="multipart/form-data">
	<input type="file" name="file" /><br /><br />
	<input type="submit" value="上传" />
</form>

②编写Servlet

页面的表单控件创建好以后,选中文件点击上传按钮请求将会提交到指定的Servlet来处理。

  • 注:这里不能像之前的servlet那样,通过request.getParameter()来获取请求参数了,当enctype="multipart/form-data"时,再使用request.getParameter()获取得到的内容为,因为浏览器发送请求的方式已经改变。既然以前的方法不能使用了,这里我们必须要引入一个新的工具来解析请求中的参数和文件,这个工具就是commons-fileupload。

1.3commons-fileupload

commons-fileupload是Apache开发的一款专门用来处理上传的工具,它的作用就是可以从request对象中解析出,用户发送的请求参数和上传文件的流。

1.4核心类

  • DiskFileItemFactory:工厂类,用于创建ServletFileUpload,设置缓存等,该类一般直接使用构造器直接创建实例
方法:
(1)public void setSizeThreshold(int sizeThreshold)	//用于设置缓存文件的大小(默认值为10kb)


(2)public void setRepository(File repository)	//用于设置缓存文件位置2.
  • ServletFileUpload:该类用于解析request对象从而获取用户发送的请求参数(包括普通参数和文件参数), 该类需要调用有参构造器创建实例,构造器中需要一个DiskFileItemFactory作为参数。
方法:
(1)public List<FileItem> parseRequest(HttpServletRequest request)//解析request对象,获取请求参数,返回的是一个List,List中保存的是一个FileItem对象,一个对象代表一个请求参数。


(2)public void setFileSizeMax(long fileSizeMax)//设置单个文件的大小限制,单位为B如果上传文件超出限制,会在parseRequest()抛出异常:FileSizeLimitExceededException


(3)public void setSizeMax(long sizeMax)//限制请求内容的总大小,单位为B,如果上传文件超出限制,会在parseRequest()抛出异常:SizeLimitExceededException
  • FileItem:该类用于封装用户发送的参数和文件,也就是用户发送来的信息将会被封装成一个FileItem对象,我们通过该对象获取请求参数或上传文件的信息。该类不用我们手动创建,由ServletFileItem解析request后返回。
(1)String getFieldName()	//获取表单项的名字,也就是input当中的name属性的值。
    
(2)String getName()			//获取上传的文件名,普通的请求参数为null。
    
(3)String getString(String encoding);	//获取内容。若为文件,将文件的流转换为字符串,若为请求参数,则获取请求参数的value。encoding参数需要指定一个字符集。

(4)boolean isFormField()	//判断当前的FileItem封装的是普通请求参数,还是一个文件。如果为普通参数返回:true,如果为文件参数返回:false。

(5)String getContentType()	//获取上传文件的MIME类型
    
(6)long getSize()		//获取内容的大小

1.5文件上传的例子

一、创建一个表单

<form action="FileUploadServlet2" method="post" enctype="multipart/form-data">
	选择文件:<input type="file" name="ufile"><br>
	<input type="submit" value="上传">
</form>

二、创建FileUploadServlet2

public class FileUploadServlet2 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter writer = response.getWriter();
		// 创建ServletFileUpload的工厂类
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 创建解析器,ServletFileUpload
		ServletFileUpload upload = new ServletFileUpload(factory);
		// 获取文件上传路径,upload的真实路径
		String realPath = this.getServletContext().getRealPath("/upload");
		// 设置单个文件的上传大小限制为:2k
		upload.setFileSizeMax(1024 * 2);

		try {
			// 通过解析器,将request解析为List<FileItem>
			List<FileItem> list = upload.parseRequest(request);
            //遍历集合
			for (FileItem fileItem : list) {
                //判断当前的FileItem封装的是普通请求参数,还是一个文件。如果为普通参数返回:true,如果为文件参数返回:false。
				if (fileItem.isFormField() == false) {
					// 获取文件名
					String fileName = fileItem.getName();
					if (fileName != null && !"".equals(fileName)) {
						// 使用UUID拼接用户名
						String uuid = UUID.randomUUID().toString().replace("-", "");
						// 上传
						File file = new File(realPath + "/" + uuid + fileName);
						fileItem.write(file);
						response.getWriter().write("upload success!");
					}
				}

			}

		} catch (FileSizeLimitExceededException e) {
			// e.printStackTrace();
			writer.write("上传单个文件过大,单个文件不能超过2k");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

2.1文件的下载

文件下载最直接的方法就是把文件直接放到服务器的目录中,用户直接访问该文件就可以直接下载。

下载文件的关键点:

  1. 服务器以一个流的形式将文件发送给浏览器。

  2. 发送流的同时还需要设置几个响应头,来告诉浏览器下载的信息。

  3. 接下来需要以输入流的形式读入硬盘上的文件

  4. 通过response获取一个输出流,并将文件(输入流)通过该流发送给浏览器

2.2文件下载的模板

以下步骤都是在同一个Servlet的doGet()方法中编写的,所下载的文件是放在WEB-INF下mp3文件夹中的文件。

①获取文件的流

//获取真实路径
String realPath = getServletContext().getRealPath("/WEB-INF/mp3/中国话.mp3");
//获取文件的File对象
File file = new File(realPath);
//获取文件的输入流
FileInputStream is = new FileInputStream(file);

②获取头文件

//获取文件的MIME信息
String contentType = getServletContext().getMimeType(realPath);
//设置下载文件的名字
String filename = "zhongguohua.mp3";
//创建Content-Disposition信息
String disposition = "attachment; filename="+ filename ;
//获取文件长度
long size = file.length();

③设置头信息

//设置Content-Type
response.setContentType(contentType);
//设置Content-Disposition
response.setHeader("Content-Disposition", disposition);
//设置文件长度
response.setContentLength((int)size);

④发送文件

//通过response获取输出流,用于向浏览器输出内容
ServletOutputStream out = response.getOutputStream();
//将文件输入流通过输出流输出
byte[] b = new byte[1024];
int len = 0;
while((len=is.read(b))> 0){
	out.write(b, 0, len);
}
//最后不要忘记关闭输入流,输出流由Tomcat自己处理,我们不用手动关闭
is.close();

2.3例子

<body>
<h2>资源库</h2>
<a href="${pageContext.request.contextPath }/DownLoadServlet2?fName=st.jpg">st.jpg</a>
<a href="${pageContext.request.contextPath }/DownLoadServlet2?fName=OSI.pptx">OSI.pptx</a>
<a href="${pageContext.request.contextPath }/DownLoadServlet2?fName=坚持.mp4">坚持.mp4</a>

</body>
public class DownLoadServlet2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
        GET请求乱码问题解决:修改服务器中service.xml中的<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080"  protocol="HTTP/1.1" redirectPort="8443"/>
        */
       // post请求在Servlet中解码,默认的字符集是ISO-8859-1,不支持中文,我们需要修改Servlet的字符集为UTF-8.
		request.setCharacterEncoding("UTF-8");
        //将服务器编码与浏览器解码设置为UTF-8
		response.setContentType("text/html;charset=UTF-8");
		//取fName值
		String fileName = request.getParameter("fName");
		System.out.println("fileName:"+fileName);
		//获取fName的真实路径
		String realPath = this.getServletContext().getRealPath("/download/"+fileName);
		System.out.println("realPath:"+realPath);
		
		//设置浏览器响应体文件类型
		String mimeType = request.getServletContext().getMimeType(fileName);
		response.setContentType(mimeType);
		//获取客户端信息
		String header = request.getHeader("User-Agent");
		//解决文件名中文乱码问题
		if(header != null && header.contains("Firefox")) {
            //火狐浏览器乱码的解决方法
			fileName = "=?utf-8?B?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?=";
		}else {
            //其他浏览器解决乱码问题
			fileName = URLEncoder.encode(fileName, "UTF-8");
		}
		//设置浏览器响应体内容格式,为附件格式。(告诉浏览器,文件为附件,别打开,下载。)
		response.setHeader("Content-Disposition", "attachment; filename="+fileName);
		
		
		//创建输入流的文件(路径+文件名)
		File file = new File(realPath);
		//创建输入流
		FileInputStream fis = new FileInputStream(file);

		//创建输出流
		ServletOutputStream sos = response.getOutputStream();
		//实现边读边写(文件下载)
		byte[] b = new byte[1024];
		int len = 0;
		while((len = fis.read(b))>0) {
			sos.write(b, 0, len);
		}
		
		sos.close();
		fis.close();
		
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

注:注意乱码解决时,代码放置的位置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值