您的位置:首页 > Web前端 > JavaScript

jsp之文件的上传和下载

2016-07-18 22:16 281 查看
1.文件的上传

[1] 简介

将本地的文件传输到远程的服务器

上传文件需要通过表单来上传

上传文件实际上就是上传文件的流

[2] 表单的设置

我们使用type为file的input来上传文件,且method为post请求

form中有一个属性enctype

默认值是application/x-www-form-urlencoded,

该值的意思是请求体中的内容将会被URL编码

当上传文件的时候,并不希望请求体被URL编码,所以我们要修改该值

在文件上传时enctype的值应该设置为multipart/form-data

multipart/form-data:多部件的表单数据,当表单enctype设置为该值时,

表单中的数据将会分为多个部件上传到服务器

当多部件表单的形式上传文件时,表单的请求体将会被分成多个部分,

一个表单项对应了一个部件,多个部件使用类似于

—————————–7df232f2e07a4 这样的分割符分割

当表单设置为多部件表单时,那么request.getParameter()这个方法就废了。

[3] FileUpload

当接收是一个多部件表单时,我们需要手动的去解析表单中的内容,但是我们说手动解析太麻烦了。

我们使用commons-fileupload来解析表单

commons-fileupload 依赖于 commons-io , 所以使用时需要同时导入2个jar包

commons-fileupload-1.3.1.jar

commons-io-2.4.jar

核心类:

DiskFileItemFactory

工厂类,用来构建解析器类实例

DiskFileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload

ServletFileUpload upload = new ServletFileUpload(factory);

- 解析器类,用来解析request,获取表单信息

FileItem

List< FileItem> list=upload.parseRequest(request);

FileUpload会将表单中每一个部件都封装为一个FileItem对象,我们可以通过读取FileItem对象来解析表单信息

方法:

boolean isFormField() –> 判断当前FileItem是否是一个普通表单项,如果是则返回true , 否则返回false

String getFieldName() –> 获取表单的name属性的值

String getString(String encoding) –> 获取表单项的value属性值,也就是我们填写的内容

String getName() –> 获取上传文件的名字

String getContentType() –> 获取上传文件的类型,返回是一个文件的MIME值

long getSize() –> 获取上传文件的大小

void write(File file) –> 将上传文件写入到指定的文件中。

使用步骤:导入第三方jar包

1.创建工厂类实例

2.创建解析器类实例

3.解析request,获取表单信息

[4] 细节

问题1:

部分浏览器选择文件以后,上传的文件的名字,是文件的全路径,具体如下:

C:\Users\zhao\Desktop\day16\图片\企鹅.jpg

这种情况我们需要对文件名进行一个截取的操作

1.判断文件名中是否包含 \

if(name.contains("\\")){

int p =name.lastIndexOf("\\")+1;

name = name.substring(p);

}


问题2:

当用户上传同名文件时,先上传的文件会被后上传的给替换。

可以来修改一下文件名,我们需要为文件名加上一个唯一的标识

将文件名修改为 唯一标识_文件名

String prefix = UUID.randomUUID().toString().replace("-", "");

String fileName = prefix+"_"+name;


问题3:

如何限制上传文件的大小

单个文件的大小

通过调用解析器ServletFileUpload的setFileSizeMax()方法可以来限制单个文件的大小。

当设置了这个值以后,文件超出范围以后,会在程序抛出异常如下异常:

FileSizeLimitExceededException

我们可以通过捕获该异常的方式来处理文件大小超过限制

catch(FileSizeLimitExceededException e){

//出现该异常,说明单个文件大小超过限制,设置一个错误消息

request.setAttribute(“msg”, “单个文件不要超过50kb”);

//转发到index.jsp

request.getRequestDispatcher(“/index.jsp”).forward(request, response);

}

所有文件的大小

通过setSizeMax()来设置所有上传文件总的大小

当文件超出限制时,会抛出如下异常

SizeLimitExceededException

我们可以捕获异常并作出相应处理

catch(SizeLimitExceededException e){

//出现该异常,说明文件总大小超过限制,设置一个错误消息

request.setAttribute(“msg”, “文件总大小不要超过150KB”);

//转发到index.jsp

request.getRequestDispatcher(“/index.jsp”).forward(request, response);

}

2.文件的下载(理解)

[1] 简介

从远程服务器将文件下载到本地

一般下载文件我们只需要将文件的地址发送给浏览器即可,

但是当浏览器访问的是一个它可以打开的文件,浏览器会自动打开

如果我们将文件直接放到根目录下的,那么将不能限制文件的下载权限

下载实际上就是将文件以流的形式发送给浏览器

[2] 下载所需要的内容

1.获取到文件的流

被下载的文件的流

2.设置两个响应头

Content-Type –> 被下载的文件的类型,需要设置一个文件的MIME值

Content-Disposition –> 告诉浏览器如何处理文件

设置值为:attachment; filename=文件名

attachment告诉浏览器文件是一个附件,直接下载到本地

filename告诉浏览器文件的名字

[3] 下载相关的两个响应头

1) 文件类型 Content-Type –> 文件的MIME类型

2) 下载文件的信息 Content-Disposition –> attachment; filename=文件名

[4] 乱码问题

文件名字是设置到响应头中,但是我们响应头不支持直接写中文,所以如果文件名为中文,会出现乱码。

所以当向响应头中设置中文需要对文字进行编码

大部分浏览器使用如下代码对文件名编码即可

URLEncoder.encode(fileName, "utf-8");


但是,火狐使用的BASE64进行的编码,上边那种方式他不支持,我们单独处理

fileName = "=?utf-8?b?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?=";


第一种方式:

//可以使用如下代码解决乱码问题

//在不同浏览器中需要调用不同代码,为了兼容不同的浏览器,我们需要在编码之前,对浏览器进行一个判断

//获取User-Agent这个请求头

String ua = request.getHeader("User-Agent");

//判断当前浏览器是否为火狐

if(ua.contains("Firefox")){

//是火狐

fileName = "=?utf-8?b?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?=";

}else{

//对fileName进行URL编码

//encode需要两个参数,第一个被编码的字符串,第二个使用字符集

fileName = URLEncoder.encode(fileName, "utf-8");

}


第二种方式:

原理:谁问跟谁急

fileName = new String(fileName.getBytes("gbk"), "iso8859-1");


先用gbk给字符解码,然后在使用iso8859-1进行编码

这种方式有点小问题,有一些特殊字符不太支持,但是大部分都好使

//获取ServletContext

ServletContext servletContext = getServletContext();

//获取文件的真实路径

String realPath = servletContext.getRealPath("/WEB-INF/爱的就是你.mp3");

//获取文件名

String fileName = "爱的就是你.mp3";

处理文件名的乱码问题......

//获取被下载文件的流

InputStream in = new FileInputStream(realPath);

//获取文件的MIME类型

String mimeType = servletContext.getMimeType(realPath);

//设置文件的MIME类型

response.setContentType(mimeType);

//设置Content-Disposition这个响应头

response.setHeader("Content-Disposition", "attachment; filename="+fileName);

//将文件的流发送给浏览器

//获取一个和浏览器对接的输出流,将文件的流发送出去

ServletOutputStream out = response.getOutputStream();

//将输入流写到输出流

IOUtils.copy(in, out);

//关闭输入流

in.close();


3.国际化(I18N)(理解)

[1]国际化简介

国际化指的是一个网站当中国人访问显示中文,外国人访问显示外语。

国际化主要指的支持英语

[2]国际化的原理

我们的国际化操作实际就是在项目提供不同国际化资源文件,ResourceBundle可以根据不同Locale来加载不同的国际资源文件

[3]核心类

java.util.ResourceBundle 用来管理国际化资源文件

java.util.Locale 来表示国家和语言的信息

国际化资源文件:

1.国际化资源文件必须创建到类路径下

2.命名规范: 基础名语言国家.properties

基础名:可以随便起

语言:使用语言

zh,en

国家:所在的国家

CN,US

[4]格式化标签库

> 我们可以使用JSTL的fmt标签来进行国际化操作:

> 导入JSTL的jar包

> 在页面中引入指定的标签库:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<fmt:setBundle basename="基础名"/>

指定使用的国际化资源文件的基础名

{setBundle 是全局的,bundle是局部的,只在其标签体内有效。}

<fmt:setLocale value="zh_CN"/>

手动指定当前Locale对象

<fmt:message key="" />

在jsp中引用国际化资源文件中的内容,key的值对应国际化资源文件中的key值。

<fmt:formatDate dateStyle="full" timeStyle="full" value="<%=new Date() %>" type="both"/>

<fmt:formatDate value>


国际化日期:

dateStyle

timeStyle

指定日期和时间的风格

可选值:FULL LONG MEDIUM SHORT
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: