文件下载的实现:
下载方式:
一.超链接下载
<a href="/项目名/download/测试.txt">下载 day10.txt</a>
若浏览器能解析该资源的mime类型,则在网页打开显示文件;若不能接下则下载;
二.编码下载
1.通过servlet完成时:
<a href="/day10/download?name=day10.txt"> //访问DownloadServlet下载 day10.txt文件
a.设置传输文件的mime类型
String mimeType=servletContext.getMimeType(文件名)
response.setContentType(mimeType);
b.设置下载头信息 content-disposition
response.setHeader("content-disposition", "attachment;filename="+文件名称);
注意:为了避免文件名称下载时中文显示不出来,需要按照浏览器对对文件名称进行编码
public static String getName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
c.提供流
response.getOutputStream();
文件传输时:使用commons-io工具类
对拷流:
IOUtils.copy(is,os);
代码示例:
//获取下载文件的名称
String filename = request.getParameter("name");
//注意中文乱码:
filename=new String(filename.getBytes("iso8859-1"),"utf-8");
ServletContext context = this.getServletContext();
//文件下载
//1.设置文件的mimeType
String mimeType = context.getMimeType(filename);
response.setContentType(mimeType);
//2.设置下载的头信息
//方式1:常见的浏览器将文件名称使用utf-8 但不兼容火狐 不推荐
//response.setHeader("content-disposition", "attchment;filename="+URLEncoder.encode(filename, "utf-8"));
//方式2:网络上的方式 (8成好使)
//response.setHeader("content-disposition", "attachment;filename="+new String(filename.getBytes("gbk"),"iso8859-1"));
//方式1:通过的方式 通过工具类编码
String _filename=DownLoadUtils.getName(request.getHeader("user-agent"), filename);
response.setHeader("content-disposition", "attachment;filename="+_filename);
//3.对拷流
//获取输入流
InputStream is = context.getResourceAsStream("/download/"+filename);
//获取输出流
ServletOutputStream os = response.getOutputStream();
IOUtils.copy(is, os);
os.close();
is.close();
文件上传实现:
1.最原始的方法:使用Web 3.0时,自己去解析表单上传的内容
使用步骤:
浏览器端的要求:
表单的提交方式必须是post
表单必须有文件上传组件<imput type="file" name="uploadFile">
表单设置 enctype属性,属性值为 multipart/form-data
服务器获取的时候:
servlet3.0要求
在接收参数的Servlet上添加一个@MultipartConfig
获取普通的组件
request.getParameter(name属性的值)
获取文件上传组件
Part part=request.getPart("uploadFile") :上传组件name属性的值
//获取文件的名称,自处理截取才能获取文件名称
Stirng sss=part.getHeader("content-disposition")
sss.substring(sss.indexof("filename=")+10,sss.length-1);
//获取上传文件对应的输入流
part.getInputStream();
//删除临时文件
part.delete()
上传时候需要注意的问题:
文件重名 随机名称
文件安全 重要的文件放在 web-inf meta-inf 服务器磁盘
目录分离
时间
用户
文件个数
随机目录
2.自己使用Apache组织提供的 commons-fileupload工具类进行表单内容解析
使用步骤:
浏览器端的要求:
表单的提交方式必须是post
表单必须有文件上传组件<imput type="file" name="uploadFile">
表单设置 enctype属性,属性值为 multipart/form-data
服务器获取的时候:
//创建一个磁盘文件项工厂
1.DiskFileItemFactory factory = new DiskFileItemFactory();
//创建一个核心文件上传对象 ServletFileUpLoad
2.ServletFileUpload upload = new ServletFileUpload(factory);
//使用上传对象调用方法去解析请求,获取一个List<FileItem>
3.List<FileItem> list = upload.parseRequest(request);
//遍历list获取每一个文件项
isFormFiled():判断是否是普通上传组件
true:普通上传组件
false:文件上传组件
getFiledName():获取表单子标签的name属性值
//若是普通的上传组件
getString("utf-8"):获取用户输入的值
//若是文件上传组件
getName():获取上传文件的名称
getInputStream():获取上传文件流
//最后删除临时文件
delete()
参考代码:
//0.创建map 放入前台传递的数据
HashMap<String, Object> map = new HashMap<>();
//创建磁盘文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建核心上传对象
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> list = upload.parseRequest(request);
//遍历集合
for (FileItem fi : list) {
//判断是否是普通的上传组件
if(fi.isFormField()){
//普通上传组件
map.put(fi.getFieldName(),fi.getString("utf-8"));
}else{
//文件上传组件
//获取文件名称
String name = fi.getName();
//获取文件的真实名称 xxxx.xx
String realName = UploadUtils.getRealName(name);
//获取文件的随机名称
String uuidName = UploadUtils.getUUIDName(realName);
//获取文件的存放路径
String path = this.getServletContext().getRealPath("/products/1");
//获取文件流
InputStream is = fi.getInputStream();
//保存图片
FileOutputStream os = new FileOutputStream(new File(path, uuidName));
IOUtils.copy(is, os);
os.close();
is.close();
//删除临时文件
fi.delete();
//在map中设置文件的路径
map.put(fi.getFieldName(), "products/1/"+uuidName);
}
}
3.使用Struts 实现(Struts2框架的使用拦截器完成了文件上传,已近使用Apache的commons-fileupload完成了解析)
使用步骤:
浏览器端的要求:
客户端表单的三个注意事项
1. method="post"
2. enctype="multipart/form-data"
3. <input type="file" name="myfile">
服务器获取的时候:
fileUpload拦截器 默认在 defaultStack 栈中, 默认会执行的
在Action中编写文件上传,需要定义三个属性(使用属性注入让Struts2注入,提供set方法)
> 文件-类型File ,
属性名:与表单中文件组件的name属性名一致.
> 文件类型-类型String , 属性名:前段是name属性名一致 + ContentType;
> 文件名-类型String ,
属性名:前段是name属性名一致+FileName;
> 可以通过FileUtils提供 copyFile 进行文件复制,将上传文件 保存到服务器端
文件上传中存在的问题:
1.先配置input逻辑视图处理错误信息,拦截器在发现错误时默认会跳转的对应input的界面
2.文件上传的总大小默认值是2M,如果超过了2M,程序会报出异常。可以使用<s:actionError>来查看具体信息!
> 解决总大小的设置,找到常量:
* struts.multipart.parser=jakarta
-- 默认文件上传解析器,就是FileUpload组件
* struts.multipart.saveDir=
-- 文件上传的临时文件存储目录
* struts.multipart.maxSize=2097152
-- 文件上传的最大值(总大小),默认是2M
> 可以在struts.xml中设置常量,修改文件上传的默认总大小!!!
* <constant name="struts.multipart.maxSize" value="5000000"></constant>
3.还可以通过配置拦截器来设置文件上传的一些属性
先在<action>标签中引入文件上传的拦截器
<interceptor-ref name="defaultStack">
<!-- 设置单个上传文件的大小 -->
<param name="fileUpload.maximumSize">2097152</param>
<!-- 设置扩展名 -->
<param name="fileUpload.allowedExtensions">.txt</param>
</interceptor-ref>