您的当前位置:首页正文

文件的上传和下载

2020-02-06 来源:步旅网
20121227 周四

文件的上传和下载

1. What is 文件上传? what is 文件下载? 文件上传:用户通过浏览器向服务器提交文件,并由服务器保存 文件下载:用户通过浏览器从服务器上得到一些文件数据,并在浏览器端保存 2. Why use 文件上传? Why use 文件下载? web应用功能需要 3. How 实现文件上传? ** 实现文件上传的流程 1、在jsp页面添加form表单: (1) (2) 必须把 form 的 enctype 属性设为 multipart/form-data,

enctype 属性取值:

application/x-www-form-urlencoded:表单 enctype 属性的默认值。这种编码方案使用有限的字符集,当使用了非字母和数字时,必须用”%HH”代替(H 代表十六进制数字)。对于大容量的二进制数据或包含非 ASCII 字符的文本来说,这种编码不能满足要求。

multipart/form-data:form 设定了enctype=“multipart/form-data”属性后,表示表单以二进制传输数据 。在浏览器在上传文件时,将把文件数据附带在 http 请求消息体中,并使用 MIME 协议对上传文件进行描述,以方便接收方对上传数据进行解析和处理。

(3) 表单提交的方式要是 post(get的请求体有大小限制,而post无大小限制) 注意:enctype=“multipart/form-data”的表单在servlet中不能再像以往那样通过 request.getParameter()那样得到请求中的参数数据(数据格式不对),另有取值的方式 2、为了方便用户处理上传数据,Apache 提供了一个用来处理表单文件上传的开源组件: Commons-fileupload 和Commons-io ,Commons-fileupload 组件从 1.1 版本开始依赖 commons-io

其主要的接口和类有三个:

1.ServletFileUpload 负责处理上传的文件数据,并将每部分的数据封装成一到 FileItem 对象中。

isMultipartContent(HttpServletRequest request) 判断上传表单是否为 multipart/form-data

parseRequest(HttpServletRequest request) :得到请求所有表单项的数据对象,返回一 个List setFileSizeMax(long fileSizeMax) 设置上传文件的最大值。 setSizeMax(long sizeMax) 设置上传文件总量的最大值

2.DiskFileItemFactory 是创建 FileItem 对象的工厂,在这个工厂类中可以配置内存缓冲区大小和存放临时文件的目录。

setSizeThreshold(int sizeThreshold,File repository )

设置内存缓冲区的大小,默认值为 10k 当上传文件大于缓冲区大小时,fileupload 组件将使用临时文件缓存上传文件

setRepository(File repository) 指定临时文件目录,默认值为 System.getProperty(\"java.io.tmpdir\")

3.FileItem :代表一个表单项数据,可以获得表单项的数据,可以判断是否为普通表单项

isFormField():为true,为普通表单项;为false,为file表单项 getFieldName() 获取的是普通表单项的表单项名。

getString(encod) 获取的是普通表单项的表单项值。 getName() 获取的是上传文件的简单文件名(有些浏览器(ie)会返回文件的全路径名,所有在此处最好加以判断)

3. 基本的原理为:

FileUpload组件将页面提交的所有元素(普通form表单域,如text和文件域file)都看作一样的FileItem,这样上传页面提交的 request请求也就是一个FileItem的有序组合,FileUpload组件可以解析该request,并返回一个一个的FileItem。而对每一个FileItem,FileUpload组件可以判断出它是普通form表单域还是文件file域,从而根据不同的类型,采取不同的操作--如果是表单域,就读出其值,如果是文件域,就保存文件到服务器硬盘上或者内存中。

4、fileuplpad 组件的具体工作流程

(1)客户端将数据封装在 request 对象中

(2)服务器端获取到 request 对象,并判断enctype的属性是否为 multipart/form-data,为true则继续进行文件上传的工作

ServletFileUpload.isMultipartContent(request)

(3)创建FileItem的工厂 DiskFileItemFactory ,并在此处设置缓冲区大小和超出 缓存时,存放临时文件的文件夹

DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(1024*10) factory.setRepository(tempFile); 以上的设置也可写成这般:

DiskFileItemFactory factory = new DiskFileItemFactory(1024*20, tempFile) (4)创建解析器ServletFileUpLoad,将解析器工厂放入解析器构造函数中。

ServletFileUpload fileUpload = new ServletFileUpload(factory); 设置响应头的编码格式

fileUpload.setHeaderEncoding(\"utf-8\");

限制单个文件的大小

fileUpload.setFileSizeMax(1024*80); 限制文件的总大小

fileUpload.setSizeMax(1024*1024);

(5)用解析器对 request 进行解析,得到的是List,每个FileItem对象 代表一个表单项数据。遍历得到的list

List list = fileUpload.parseRequest(request); For(FileItem item:list) (6)判断代表每个表单项的 FileItem 是否为普通表单项 isFormField,返回 true 为普通表单项。

if(item.isFormField()) (7)如果是普通表单项,通过 getFieldName 获取表单项名,getString 获得表单 项值。

True

获得普通表单项的名字哦

String fieldName = item.getFieldName();

获得普通表单项的属性值,可以设置解码的格式 String value = item.getString(\"utf-8\"); (8)如果 isFormField 返回 false 那么是用户要上传的数据,可以通过 getInputStream 获取上传文件的数据。

False

String fieldName = item.getFieldName(); String fileName = item.getName();

//由于有些浏览器输出的是全路径,故需加判断 if(fileName!=null && fileName.contains(\"\\\\\")) {

fileName = fileName.substring(fileName.lastIndexOf(\"\\\\\")+1); }

//保存上传的文件

InputStream is = item.getInputStream();

(9)把上传的数据保存在服务端(uploadDirFile为保存在服务端的文件夹路径(自 己设置),fileName为保存的文件名)

OutputStream os = new FileOutputStream(new File(uploadDirFile, fileName));

byte[] buffer = new byte[1024]; int len = -1; while((len=is.read(buffer))>0) { os.write(buffer, 0, len); } os.close(); is.close();

//删除可能生成的临时文件 item.delete();

How 实现文件下载?

有两种方式

① 将文件资源直接放在WebContent的路径下(不放入WEB-INF中),在页面直接提供可供访问的链接:WebContent/download/china.jpg

china.jpg

问题:

1.像图片和txt等浏览器可以直接打开的文件,浏览器会自动打开而不是主动提供下载;当然,向doc和压缩文件等浏览器不能直接打开的文件,浏览器提供下载功能

2.太暴露了,不安全,有时需要有一定的权限才能下载,但这样没有办法控制

② 通过servlet提供下载,我们可以对下载进行控制,资源文件存放在WEB-INF中

china.jpg
通过servlet提供下载不需要别的jar包,相比文件的上传较为简单 1.在响应头中加入两条响应信息 Content-Type: application/x-msdownload Content-Disposition: attachment;filename=fileName

其中fileName是下载文件的文件名,china.jpg,是页面请求时传过来的参数

String filename = request.getParameter(\"filename\");

response.setHeader(\"Content-Type\

response.setHeader(\"Content-Disposition\

2.获得资源文件的位置,读取文件数据

String downloadDir = getServletContext().getRealPath(\"/WEB-INF/download\"); InputStream is = new FileInputStream(new File(downloadDir,fileName));

3.把读取的数据写入浏览器端

OutputStream os = response.getOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len=is.read(buffer))>0){ os.write(buffer, 0, len); } os.close(); is.close();

文件上传的UploadServlet源程序: 关联的jar包:

commons-io-2.0.jarcommons-fileupload-1.2.1.jar

package jin.fileuplad; import java.io.File;

import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List;

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.FileSizeLimitExceededException; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class RegistJinServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //判断是否为带文件的请求,form表单的enctype=multipart/form-data boolean flag = ServletFileUpload.isMultipartContent(request); if(flag){ File tempFile = new File(\"F:\\\emp\"); if(!tempFile.exists()){ tempFile.mkdirs(); } DiskFileItemFactory factory = new DiskFileItemFactory(1024*10,tempFile); //设置缓冲区大小,若文件超出此值则将其临时存放在temp中 //factory.setSizeThreshold(1024*10); //设置临时存放的位置 //factory.setRepository(tempFile); ServletFileUpload fileUpload = new ServletFileUpload(factory); //设置上传的单个文件的最大字节数为40k fileUpload.setFileSizeMax(1024*40);

response.setContentType(\"text/html;charset=utf-8\"); try { List list = fileUpload.parseRequest(request); for(FileItem item:list){ if(item.isFormField()){ String fieldName = item.getFieldName(); String value = item.getString(\"utf-8\"); }else{ String fieldName = item.getFieldName(); String fileName = item.getName(); if(fileName!=null&&fileName.contains(\"\\\\\")){ fileName = fileName.substring(fileName.lastIndexOf(\"\\\\\")+1); } InputStream is = item.getInputStream(); //确定一个文件的保存目录 String uploadDir = this.getServletContext().getRealPath(\"/load\"); File uploadDirFile = new File(uploadDir); if(!uploadDirFile.exists()){ uploadDirFile.mkdirs(); } OutputStream os = new FileOutputStream(new File(uploadDirFile,fileName)); byte[] buffer = new byte[1024]; int len = -1; while((len=is.read(buffer))>0){ os.write(buffer, 0, len); } os.flush(); os.close(); is.close(); item.delete(); response.getWriter().write(\"上传成功\"); System.out.println(); } } } catch (FileSizeLimitExceededException e) { response.getWriter().write(\"文件大于40k\"); } catch (FileUploadException e) { e.printStackTrace(); } } }

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws

ServletException, IOException {

doGet(request, response); } }

文件上传的jsp页面:upload.jsp

用户名:
头像:

文件下载的DownloadServlet源程序 package jin;

import java.io.File;

import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

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

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

public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String fileName = request.getParameter(\"filename\"); response.setHeader(\"Content-Type\ response.setHeader(\"Content-Disposition\ //资源文件存放在此文件夹下 String downloadDir = getServletContext().getRealPath(\"/WEB-INF/download\"); InputStream is = new FileInputStream(new File(downloadDir+\"/\"+fileName)); OutputStream os = response.getOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len=is.read(buffer))>0){ os.write(buffer, 0, len); }

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

文件下载的jsp页面:download.jsp

下载列表

1.jpg
2.jpg
3.jpg

因篇幅问题不能全部显示,请点此查看更多更全内容