文件上传和下载
文件上传
- 实现web开发中的文件上传功能,需完成如下二步操作
- 在web页面中添加上传输入项
- 在servlet中读取上传文件的数据,并保存到本地硬盘中。
- 如何在web页面中添加上传输入项?
- <input type=“file”>标签用于在web页面中添加文件上传输入项,设置文件上传输入项时须注意:
- 必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据。
- 必须把form的enctype属值设为multipart/form-data.设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理
可以使用Request对象提供了一个getInputStream方法,但是会特步麻烦。因此,Apache 开源组织提供了一个用来处理表单文件上传的一个开源组件(Commons-fileupload),该组件性能优异,并且其API使用极其简单,可以让开发人员轻松实现web文件上传功能,因此在web开发中实现文件上传功能,通常使用Commons-fileupload组件实现
- Commons-fileupload组件使用
需要导入Commons-fileupload和commons-io
核心API--DiskFileItemFactory
DiskFileItemFactory 是创建 FileItem 对象的工厂,这个工厂类常用方法:
public void setSizeThreshold(int sizeThreshold)
- 设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。
public void setRepository(java.io.File repository)
- 指定临时文件目录,默认值为System.getProperty("java.io. tmpdir").
public DiskFileItemFactory(int sizeThreshold, java.io. File repository)
- 构造函数
- 核心API--ServletFileUpload
ServletFileUpload 负责处理上传的文件数据,并将表单中每个输入项封装成一个 FileItem 对象中。常用方法有:
- boolean isMultipartContent(HttpServletRequest request)
判断上传表单是否为multipart/form-data类型
- List parseRequest(HttpServletRequest request)
解析request对象,并把表单中的每一个输入项包装成一个fileItem对象,并返回一个保存了所有FileItem的list集合
- setFileSizeMax(long fileSizeMax)
设置上传文件的最大值
- setSizeMax(long sizeMax)
设置上传文件总量的最大值
- setHeaderEncoding(java.lang.String encoding)
设置编码格式
- setProgressListener(ProgressListener pListener)
设置进度条
public class UploadServlet3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{
//1.得到解析器工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.得到解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//3.判断上传表单的类型
if(!upload.isMultipartContent(request)){
//上传表单为普通表单,则按照传统方式获取数据即可
return;
}
//为上传表单,则调用解析器解析上传数据
List<FileItem> list = upload.parseRequest(request); //FileItem
//遍历list,得到用于封装第一个上传输入项数据fileItem对象
for(FileItem item : list){
if(item.isFormField()){
//得到的是普通输入项
String name = item.getFieldName(); //得到输入项的名称
String value = item.getString();
System.out.println(name + "=" + value);
}else{
//得到上传输入项
String filename = item.getName(); //得到上传文件名 C:\Documents and Settings\ThinkPad\桌面\1.txt
filename = filename.substring(filename.lastIndexOf("\\")+1);
InputStream in = item.getInputStream(); //得到上传数据
int len = 0;
byte buffer[]= new byte[1024];
//用于保存上传文件的目录应该禁止外界直接访问
String savepath = this.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println(savepath);
FileOutputStream out = new FileOutputStream(savepath + "\\" + filename); //向upload目录中写入文件
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- 注意问题:
- 上传文件名的中文乱码和上传数据的中文乱码
upload.setHeaderEncoding("UTF-8"); //解决上传文件名的中文乱码
//表单为文件上传,设置request编码无效,只能手工转换
1.1 value = new String(value.getBytes("iso8859-1"),"UTF-8");
1.2 String value = item.getString("UTF-8");
-
为保证服务器安全,上传文件应该放在外界无法直接访问的目录
-
为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
-
为防止一个目录下面出现太多文件,要使用hash算法打散存储
-
要限制上传文件的最大值,可以通过:
ServletFileUpload.setFileSizeMax(1024)方法实现,并通过捕获:FileUploadBase.FileSizeLimitExceededException异常以给用户友好提示
-
想确保临时文件被删除,一定要在处理完上传文件后,调用item.delete方法
-
要限止上传文件的类型:在收到上传文件名时,判断后缀名是否合法
8、监听文件上传进度:
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
}
});
- 在web页面中动态添加文件上传输入项
function addinput(){
var div = document.getElementById("file");
var input = document.createElement("input");
input.type="file";
input.name="filename";
var del = document.createElement("input");
del.type="button";
del.value="删除";
del.onclick = function d(){
this.parentNode.parentNode.removeChild(this.parentNode);
}
var innerdiv = document.createElement("div");
innerdiv.appendChild(input);
innerdiv.appendChild(del);
div.appendChild(innerdiv);
}
文件下载
response.setContentType("application/x-msdownload");
String str="attachment;filename="+URLEncoder.encode(fileName,"UTF-8“);
response.setHeader("Content-Disposition",str)
用response.getOutputStream方法返回 ServeltOutputStream 对象来向客户端 写入文件内容