文件上传
文件上传的前提
a.提供form表单,method必需是post
b.form表单的enctype必需multipart/form-data
c.提供input type="file"类的上传输入域
enctpe(编码类型)告诉服务器请求类型,与属性Context-type作用一致。
application/x-www-form-urlencoded(默认):默认传递的是表单数据,名字和值
multipart/form-data:请求正文
1.这时候请求正文改变了,成字节流传递!!(其中有表单text和file控件提交的正文xi)
文件上传注意事项
服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
可以用request.getInputStream()来获取表单提交的字节流信息,然后对字节流信息截取,获取上传文件的信息。
工具类:fileupLoad
fileupload是由apache的commons组件提供的上传组件,它主要工作就是帮我们解析request.getInputStream()。
步骤:
1.导入commons-fileupload.jar(核心包)和commons-io.jar(依赖包),前者解析字节流,后者涉及读写
fileupload核心类
DiskFileItemFactory(磁盘对象,加载后者) ServletFileUpload(核心对对象) FileItem(表单项)
表单项:form提交表单中一个file一个text一个radio都是代表一个表单项,对应一个FileItem类
fileupload简单应用
使用fileupload组件的步骤如下:
1. 创建工厂类DiskFileItemFactory对象:
DiskFileItemFactory factory = new DiskFileItemFactory()
2. 使用工厂创建解析器对象:
ServletFileUpload fileUpload = new ServletFileUpload(factory)
3. 使用解析器来解析request对象:
List<FileItem> list = fileUpload.parseRequest(request)
//判断表单是否支持文件上传
boolean multipartContent = ServletFileUpload.isMultipartContent(request);
if(!multipartContent){
throw new RuntimeException("你的表单不是上传控件");
}
//创建DiskFileItemfactory
DiskFileItemFactory factory=new DiskFileItemFactory();
//创建一个ServletFileUpload核心对象
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//解析request对象,并得到一个表单项的集合
List<FileItem> list = upload.parseRequest(request);
//遍历表单项的数据
for(FileItem fileItem:list){
//普通表单
if(fileItem.isFormField()){
String name=fileItem.getFieldName();//字段名
fileItem.getString();//获取字段内容,如果是文件字段,那么获取的是文件内容,但是文件必须是文本
}else{
//上传表单项
String name=fileItem.getName();//获取文件名
InputStream inputStream = fileItem.getInputStream();//得到文件输入流
//获取真实路径,及服务器运行时路径
String directoryRealPath=this.getServletContext().getRealPath("/upload");
System.out.println(directoryRealPath);
File storDirectory=new File(directoryRealPath);
if(!storDirectory.exists()){
//不存在的时候
storDirectory.mkdirs();//创建一个指定目录;
}
File file=new File(storDirectory,name);
FileOutputStream out = new FileOutputStream(file);//输出到磁盘
int len=0;
byte[] b=new byte[1024];
while((len=inputStream.read(b))!=-1){
out.write(b,0,len);
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
FileItem对象对应一个表单项(表单字段)。可以是文件字段或普通字段
l boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
l String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username;
l String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
l String getName():获取文件字段的文件名称; (a.txt)
l String getContentType():获取上传的文件的MIME类型,例如:text/plain。
l int getSize():获取上传文件的大小;
l InputStream getInputStream():获取上传文件对应的输入流;
l void write(File):把上传的文件保存到指定文件中。
l delete();
文件上传考虑的几个问题
//io工具类的一个获取文件后缀名的工具类
if(name!=null) {
name=FilenameUtils.getName(name);
System.out.println(name+" "+FilenameUtils.getBaseName(name));
}
//解决文件同名的问题(前面加上随机数)
name=UUID.randomUUID()+"_"+name;
4.避免同一个文件夹文件过多(一般一天一个文件夹) private String makeChildDirectory(File store) {
SimpleDateFormat sm=new SimpleDateFormat("yyyy-MM-dd");
String date = sm.format(new Date());
File file=new File(store,date);
if(!file.exists()) {
//创建目录
file.mkdirs();
}
return file.toString();
}
5.限制文件的大小(web不适合上传大的文件)单个文件大小:
ServletFileUpload.setFileSizeMax(字节)
总文件大小:(多文件上传)
ServletFileUpload.setSizeMax(字节)
6.用户没有上传问题DiskFileItemFactory:
将请求消息实体中的每一个项目封装成单独的DiskFileItem (FileItem接口的实现) 对象的任务由FileItemFactory
接口的默认实现 DiskFileItemFactory 来完成。当上传的文件项目比较小时, 直接保存在内存中(速度比较快),
比较大时,以临时文件的形式,保存在磁盘临时文件夹
(虽然速度慢些,但是内存资源是有限的)。
//以下是代码:必须设置好上传文件的最大阀值
final long MAX_SIZE = 10 * 1024 * 1024 * 1024;// 设置上传文件最大为 10G
//必须设置文件上传服务器上的临时目录
// 文件上传参数配置
// 创建一个新的文件上传句柄
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存缓冲区,超过后写入临时文件
factory.setSizeThreshold(4096);
// 设置上传到服务器上文件的临时存放目录 -- 非常重要,防止存放到系统盘造成系统盘空间不足
factory.setRepository(new File("F:\\uploadFileTemp"));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");
// 设置总文件的最大上传值
upload.setSizeMax(MAX_SIZE); // 文件上传上限10G
//上传成功后一定要删除临时目录的临时文件
fileItem.delete(); // 请务必调用,在文件上传结束后,删除临时目录的文件...
最好记录下文件从开始上传到上传结束的时间点,这个对今后文件上传时间的分析很有用
另外,因为Struts2的上传功能也引入了该包,但是却做了拦截器限制文件的最大上传大小为2M,可以通过修改它的配置文件动态更改上传文件的大小;
而且,Struts会在文件上传成功后,帮你删除掉临时文件。我这里使用的是Spring MVC,需要在上传类中指定最大上传文件大小,(这玩意一般不动
态设置,最大上传文件大小一般是系统的标准,是让使用者遵循滴),而且必须在上传成功后删除临时文件。
8.上传中文乱码问题(上传带中文文件名乱码问题)
upload.setHeaderEncoding("utf-8");
文件下载
//设置一个要下载的文件
String filename = "销售榜单.csv";
//设置文件名的编码
if(request.getHeader("user-agent").toLowerCase().contains("msie")){
filename = URLEncoder.encode(filename, "UTF-8");//将不安全的文件名改为UTF-8格式
}else{
filename = new String(filename.getBytes("UTF-8"),"iso-8859-1");//火狐浏览器
}
//告知浏览器要下载文件
response.setHeader("content-disposition", "attachment;filename="+filename);
//response.setHeader("content-type", "image/jpeg");
response.setContentType(this.getServletContext().getMimeType(filename));//根据文件名自动获得文件类型
response.setCharacterEncoding("UTF-8");//告知服务器使用什么编码
//创建一个文件输出流
PrintWriter out = response.getWriter();
out.write("电视机,20\n");
out.write("洗衣机,10\n");
out.write("冰箱,8\n");
来源:CSDN
作者:明昌昆
链接:https://blog.csdn.net/qq_33811090/article/details/78566267