1、要有一个form标签,method = post 请求
2、form标签的encType属性值必须为multipart/form-data值
3、在form标签中使用input type=file添加上传文件
4、编写服务器代码(Servlet程序)接收,处理上传的数据。
encType = multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
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所指向的硬盘位置。
上传文件的表单:
<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>
解析上传的数据的代码:
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码。
文件下载示例:
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);
}
}
如果客户端浏览器是IE浏览器或者是谷歌浏览器,我们需要使用URLEncoder类先对中文名进行UTF-8的编码操作。
因为IE浏览器和谷歌浏览器收到含有编码的字符串后会以UTF-8字符集进行解码显示。
//把中文名进行UTF-8编码操作
String str = "attachment; fileName=" + URLEncoder.encode("宇航员.jpg","UTF-8");
resp.setHeader("Content-Disposition",str);
如果客户端浏览器是火狐浏览器,那么我们需要对中文名进行BASE64的编码操作。
BASE64编解码操作:
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这个请求头携带过来的浏览器信息即可判断出是什么浏览器。
如下:
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"));
}