jsp之文件的上传和下载

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值