一键采集上传常见的细节问题(()文件上传的内容上传内容及内容解析 )
优采云 发布时间: 2022-02-28 14:25一键采集上传常见的细节问题(()文件上传的内容上传内容及内容解析
)
一:文件上传:javascript
要求:
1:jsp的页面:
一:表格形式:
b:帖子提交:
c: form 指定一个属性:enctype="multipart/form-data"
d:文件组件:
2:小服务程序:
request.getParamter("name");//不生效:
ServletInputStream in = request.getInputStream();
把得到的数据封装进去,理论上可以解析数据。
3:请求在请求正文中:css
发布请求正文:
请求第一行:
请求头信息:html
请求正文:
------------------
普通组件:只有一个标头:Content-Dispositon:name="xxx"java
请求正文:mrzhang:填写内容。
------------------
文件上传字段:两个标题:
内容处置:表单数据;;文件名="C:\Users\Mrzhang\Desktop\copy2.txt"
内容类型:文本/纯 MIMEweb
文件上传内容:
xxxx阿帕奇
- - - - - - - 大批
二:解析请求中的请求体:
1:jar:Apache组织提供的公共组件:
公共文件上传
commons-io
文件上传相关的两个组件,这两个组件是强依赖的。
2:原理:
请求体中各个组件的内容被封装成一个对象:
FileItem 对象:使用对象的方法和属性来获取数据。
3:获取文件项:
a:获取工厂:
b:获取解析器:
c:使用解析器解析请求,获取fileItme对象:
对象代码:
// 获取工厂:
DiskFileItemFactory 工厂 = new DiskFileItemFactory();
// 获取解析器:
ServletFileUpload 上传 = 新的 ServletFileUpload(Factory);
// 解析请求并获取所有 FileItem 对象:
List list=upload.parseRequest(request); 浏览器
4:FileItem类详解:
isFormField() 判断组件是普通组件还是文件上传组件:true,普通组件:false:文件上传组件:
getFieldName() 返回普通字段属性的值。name= username 获取用户名的值:
获取字符串();获取普通字段的上传内容。
文件上传组件:
获取名称();获取文件名:
获取尺寸();将以字节为单位上传文件大小。长
获取输入流();获取文件上传对应的流:
写(文件文件);将文件内容写入指定位置:
雄猫
三:文件上传的具体代码;
(1)引入jar包:
(2)准备页面:
(3)准备 Servlet:
四:详情:
1:上传的普通字段内容:乱码:getString("utf-8");
2:上传的文件不能被外界直接访问,应隐藏:目的、安全;
应该是上传到web-inf,内容不能被外界直接访问。安全
获取 web-inf/files 的位置:tomcat 上的真实位置:
ServletContext.getRealPath("/WEB-INF/files");
3:文件的文件路径问题:
不同浏览器上传的路径不一致。一些浏览器上传相对路径,而另一些浏览器上传绝对路径。大多数浏览器上传的相对路径。
一个.txt
c:\user\mrzhang\files\a.txt
提取文件名:
字符串文件名 = f2.getName();
//截距:
int index = filename.lastIndexOf("\\");
如果(索引!=-1){
文件名 = 文件名.subString(index+1);
}
4:上传文件名乱码:
request.setCharacterEncoding("utf-8");
解析器提供了一个方法:
servletFileUpload.setHeaderEncoding("utf-8");// 提供的解析器。高优先级:request.setCharacterEncoding("utf-8")的封装;
5:文件名相同的问题:
解决方案1:uuid+“文件名”。后缀名;
解决方案2:new Date().getTime()+"filename";
6:上传的文件不能在同一个目录下: 上传的目录被打散了:
a:时间分手:获取当前时间,创建目录:
b: 文件名首字母分散:abc.txt : charAt("0")
c:散列分解:
实施步骤:
(1) 获取文件名:
(2)获取哈希值:hashCode(); int
(3)转换为十六进制: Integer.toHexString(); //String: 9A8B7C
(4) 获取字符串的前两位:第一个字母为一级目录,第二个字母为二级目录。16*16
package com.yidongxueyuan.web.servlet;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/*
* 处理文件上传的servlet:
*
* 1:细节:
* 乱码解决了文件名称上传的乱码,
* 普通字段: getString("utf-8");
*
* 2:对相对路径进行了处理: subString();
*
* 3: 文件名称同名的问题,处理:
*
* 4: 哈希打散:
* filename.hashCode();
* filename.toHexString();
* filename.charAt(0);
*
* File dir= new File(root, charAt(0)+"\"+charAt(1));
*
* File destFile = new File(dir, savefilename);
*
* write();
*
*
*
*
*/
public class FileUploadServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//解决上传文件名称的乱码问题:
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");//告知客户端浏览器响应的内容: text/html charset=utf-8
/*
* 三步走:
* 1:得到工厂:
* 2: 得到解析器:
* 3:解析request:
*/
//得到得到解析器工厂;
DiskFileItemFactory factory = new DiskFileItemFactory(1024*20,new File("C:/Users/Mrzhang/javaEE/javaEE-07/temp"));
// DiskFileItemFactory factory = new DiskFileItemFactory();
//得到解析器:
ServletFileUpload upload = new ServletFileUpload(factory);
//解析以前设置上传单个文件的大小:
// upload.setFileSizeMax(1024*10);//这是最大是10K:
// upload.setSizeMax(1024*1024*10); //设置了整个request 的大小, 若是上传的request 大于设定的最大值, 也会触发异常
//解析request: 获List
try {
List fileItem = upload.parseRequest(request);
//解析fileItem当中的内容: web-inf下的: 目录安全: 不能被外界随机的访问:
FileItem f2 = fileItem.get(1);//文件上传的组件:
/*
* 得到文件的名称:
* f2.getName();
* f2.getInputStream(); 文件当中的内容:
* new FileOutputStream("path");
* 实现流对接:
*/
/*
* 得到要保存的路径:
* WEB-INF/files/
* 目的: 安全: 不能被外界直接经过浏览器访问:
* 得到ServletContext对象: 得到真实路径:
*/
String root = this.getServletContext().getRealPath("/WEB-INF/files/");
//得到上传文件的名称:
String filename = f2.getName();
/*
* 细节的处理:
* 1: 绝对路径的问题: 兼顾小部分浏览器:
*/
int index = filename.lastIndexOf("\\");
if(index != -1){//说明路径当中存在\\ :
filename = filename.substring(index+1);
}
/*
* 处理文件同名的问题: uuid
*/
String savename = CommonsUtils.uuid()+"_"+filename;
/*
* 哈希码 生产多个目录: 将上传的文件存放在多个目录当中:
*/
// 1:得到文件名称的哈希值:
int code = filename.hashCode();// int
// 2:得到code 的十六进制的值:
String hex = Integer.toHexString(code);// 9c0a1d
// 得到前两位: 充当第一层目录 和第二层目录:
char firstDir = hex.charAt(0);
char secDir = hex.charAt(1);
/*
* 得到保存的文件路径:
*/
File dirFile = new File(root, firstDir+"/"+secDir);//存放的目录:
//dirFile 若是不存在,建立:
if(!dirFile.exists()){//说明不存在
//建立“:
dirFile.mkdirs();//建立多层的目录:
}
//建立保存的文件:
File destFile = new File(dirFile, savename);
//保存:
try {
f2.write(destFile);
} catch (Exception e) {
e.printStackTrace();
}
} catch (FileUploadException e) {
// 触发异常: 说明文件过大:
request.setAttribute("msg", "您传的文件过大");
request.getRequestDispatcher("/index.jsp").forward(request, response);
e.printStackTrace();
}
}
}
文件下载
文件下载:
原来:服务器响应返回的数据:text/html 浏览器可以自动解析:
原理:现在要求服务端传递的数据是字节数组:服务端只需要响应一个字节流。
下载具有两个标头的流需要满足的条件:
Stream:服务器端响应返回的字节流。new FileOutputStream("字符串路径");
设置两个标题:
* Content-Type:这是文件类型的 MIME 类型:text/css text/javascript : tomcat : web.xml
* Content-Disposition : 默认值:inline 在浏览器中打开。
文件下载:附件;文件名=xxxx;
下载详情:
1:下载的文件名乱码:
一般解决方案:
新字符串(name.getBytes("gbk"),"iso-8859-1");
缺点:这种方法可以解决大部分浏览器,但是个别特殊字符无法解决:
不同的浏览器对文件名进行不同的编码:
修复狐:Base64:
其他浏览器:url
2:通用方式:提供一个工具类,稍后搜索:
文件下载servlet代码如下:
package com.yidongxueyuan.web.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Encoder;
/*
* 负责下载的Servlet:
*/
public class DownLoadFileServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/* request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");*/
/*
* 1: 文件的下载具有一个流: 两个头:
*/
String filename = "C:/Users/Mrzhang/Desktop/API/a练习图片/girl.jpg";
//头信息:
// Content-Type: MIME 文件的MIME类型:
String conentType= this.getServletContext().getMimeType(filename);//可以得到.jpg文件的MIME类型: image/jpeg
String name = "凤姐.jpg";
// String savename = new String(name.getBytes("gbk"),"iso-8859-1"); 解决 大部分状况:
String savename = FilenameEncodingUtils.filenameEncoding(name, request);
String contentDisposition = "attachment;filename="+savename;
//设置响应头信息:
response.setHeader("Content-Type",conentType );
response.setHeader("Content-Disposition", contentDisposition);
//准备的一个流:
//将图片读取到fis当中:
FileInputStream fis = new FileInputStream(filename);
//响应输出流:
ServletOutputStream out = response.getOutputStream();
//流对接: IOUtils
IOUtils.copy(fis, out);
fis.close();
out.close();
}
}
class FilenameEncodingUtils {
// 用来对下载的文件名称进行编码的!
public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {
String agent = request.getHeader("User-Agent"); //获取浏览器
if (agent.contains("Firefox")) {
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"
+ base64Encoder.encode(filename.getBytes("utf-8"))
+ "?=";
} else if(agent.contains("MSIE")) {
filename = URLEncoder.encode(filename, "utf-8");
} else {
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}