文章目录
- 前言
- 一、文件的上传介绍
- 1.1、文件上传,HTTP协议的说明
- 1.2、commons-fileupload.jar 常用API介绍说明
- 1.3、fileupload类库的使用:
- 二、文件下载
- 三、附件中文名乱码的解决方案:
- 方案一:URLEncoder解决IE和谷歌浏览器中的附件中文名问题
- 方案二:BASE64编解码解决火狐浏览器的附件中文名问题
- 总结以上两种解决方案
前言
文件的上传和下载,是非常常见的功能,在很多的系统中,或者软件中都经常使用文件的上传和下载。 比如:QQ头像,就使用了上传 邮箱中也有附件的上传和下载的功能
一、文件的上传介绍
1、要有一个form标签,method = post 请求 2、form标签的encType属性值必须为multipart/form-data值 3、在form标签中使用input type=file添加上传文件 4、编写服务器代码(Servlet程序)接收,处理上传的数据。
encType = multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
1.1、文件上传,HTTP协议的说明
1.2、commons-fileupload.jar 常用API介绍说明
commons-fileupload.jar 需要依赖commons-io.jar这个包,所以两个包我们都要引入。 第一步,就是需要导入两个jar包; commons-fileupload.jar commons-io.jar 这两个jar包中常用的类和方法: ServletFileUpload类,用于解析上传的数据 FileItem类,表示每一个表单项 boolean ServletFileUpload.isMultipartContent(HttpServletRequest request); 判断当前上传的数据格式是否是多段的格式
String FileItem.getString(); 获取当前表单项的值 String FileItem,getName(); 获取上传的文件名 String FileItem,write(file); 将上传的文件写到参数file所指向的硬盘位置。
1.3、fileupload类库的使用:
上传文件的表单:
代码语言:javascript复制<body>
<form action="uploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username" /><br>
头像:<input type="file" name="photo" /><br>
<input type="submit" value="上传" />
</form>
</body>
解析上传的数据的代码:
代码语言:javascript复制public class UploadServlet extends HttpServlet {
@Override
//用来处理上传的数据
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//先判断上传的数据是否是多段数据(只有是多段的数据,才是文件上传的)
if(ServletFileUpload.isMultipartContent(req)) {
//创建FileItemFactory工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
//创建用于解析上传数据的工具类ServletFileUpload类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
//解析上传数据,得到每一个表单项FileItem
List<FileItem> list = servletFileUpload.parseRequest(req);
for(FileItem fileItem : list) {
if(fileItem.isFormField()) {
//普通表单项
System.out.println("表单项的name属性值: " fileItem.getFieldName());
//参数UTF-8解决乱码问题
System.out.println("表单项的value属性值: " fileItem.getString("UTF-8"));
} else {
//上传的文件
System.out.println("表单项的name属性值: " fileItem.getFieldName());
System.out.println("上传的文件名: " fileItem.getName());
fileItem.write(new File("E:\" fileItem.getName()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
结果:
二、文件下载
下载常用的API说明: response.getOutputStream(); servletContext.getResourceAsStream(); servletContext.getMimeType(); response.setContentType();
response.setHeader(“Content-Disposition”,“attachment; fileName = 文件名.文件类型”); 这个响应头告诉浏览器,这是需要下载的。而attachment表示附件,也就是下载的一个文件。fileName=后面表示下载的文件名。 完成上面的两个步骤,下载文件是没问题了。但是我们要下载的文件是中文名的话,会发现下载无法正确显示出正确的中文名。 原因是在响应头中,不能包含有中文的字符,只能包含ASCII码。 文件下载示例:
代码语言:javascript复制public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要下载的文件名
String downloadFileName = "宇航员.jpg";
//读取要下载的文件内容(通过ServletContext对象可以读取)
ServletContext servletContext = getServletContext();
//获取要下载的文件类型
String mimeType = servletContext.getMimeType("/file/" downloadFileName);
System.out.println("下载的文件类型: " mimeType);
//在回传前,通过响应头告诉客户端返回的数据类型
resp.setContentType(mimeType);
//还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
/* Content-Disposition 响应头,表示收到的数据怎么处理
attachment 表示附件,表示下载使用
filename 表示指定下载的文件名*/
//把中文名进行UTF-8编码操作
String str = "attachment; fileName=" URLEncoder.encode("宇航员.jpg","UTF-8");
resp.setHeader("Content-Disposition",str);
InputStream resourceAsStream = servletContext.getResourceAsStream("file/" downloadFileName);
//获取响应输出流
OutputStream outputStream = resp.getOutputStream();
//把下载的文件内容回传给客户端
//读取输入流中全部的数据,复制给输出流,输出给客户端
IOUtils.copy(resourceAsStream,outputStream);
}
}
三、附件中文名乱码的解决方案:
方案一:URLEncoder解决IE和谷歌浏览器中的附件中文名问题
如果客户端浏览器是IE浏览器或者是谷歌浏览器,我们需要使用URLEncoder类先对中文名进行UTF-8的编码操作。 因为IE浏览器和谷歌浏览器收到含有编码的字符串后会以UTF-8字符集进行解码显示。
代码语言:javascript复制 //把中文名进行UTF-8编码操作
String str = "attachment; fileName=" URLEncoder.encode("宇航员.jpg","UTF-8");
resp.setHeader("Content-Disposition",str);
方案二:BASE64编解码解决火狐浏览器的附件中文名问题
如果客户端浏览器是火狐浏览器,那么我们需要对中文名进行BASE64的编码操作。
BASE64编解码操作:
代码语言:javascript复制 public static void main(String[] args) throws Exception {
String content = "这是需要Base64编码的内容";
// 创建一个Base64编码器
BASE64Encoder base64Encoder = new BASE64Encoder();
// 执行Base64编码操作
String encodedString = base64Encoder.encode(content.getBytes("UTF-8"));
System.out.println( encodedString );
// 创建Base64解码器
BASE64Decoder base64Decoder = new BASE64Decoder();
// 解码操作
byte[] bytes = base64Decoder.decodeBuffer(encodedString);
String str = new String(bytes, "UTF-8");
System.out.println(str);
}
因为火狐浏览器使用的是BASE64的编解码方式还原响应中的汉字,所以需要使用BASE64Encoder类进行编码操作。 注:BASE64Encoder类在高版本的JDK中已经被抛弃使用了。所以用这个类慎用!
总结以上两种解决方案
我们只需要通过判断请求头中User-Agent这个请求头携带过来的浏览器信息即可判断出是什么浏览器。 如下:
代码语言:javascript复制 if (req.getHeader("User-Agent").contains("Firefox")) {
// 如果是火狐浏览器使用Base64编码
resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" new BASE64Encoder().encode("中文.jpg".getBytes("UTF-8")) "?=");
} else {
// 如果不是火狐,是IE或谷歌,使用URL编码操作
resp.setHeader("Content-Disposition", "attachment; filename=" URLEncoder.encode("中文.jpg", "UTF-8"));
}