1、文件上传
文件上传,其实就是把本机上的文件保存到web服务器端。比如文本,图片,视频等。
但是,在上传的过程中有很多要注意的问题,比如说我们提交的内容进行限制,提交中产生的乱码问题。同时服务器也应该有限制机制,防止用户提交非法文件,对服务器进行攻击,比如脚本攻击。
1、对表单的限制
1、指定提交方式
method指定为post
2、
enctype属性设置multipart/form-data
enctype属性规定在发送到服务器之前应该如何对表单数据进行编码,默认地,表单会编码为“application/x-www-form-urlencoded”,也就是说,发送到服务器之前,所有字符都会进行编码(空格转换为 “+” 加号,特殊符号转换为 ASCII HEX 值)。
它的值形式如下:%E5%BC%A0%E4%B8%89
通过抓包获取提交设置enctype=”multipart/form-data”
信息如下:
通过使用enctype=”multipart/form-data”得到返回的数据信息
1、表单上每一部分都是独立的
2、每一部分都有自已的消息头和消息体
3、普通表单项
Content-Disposition: form-data; name=”xxx”(表单项名称)
文件表单项
消息头:Content-Disposition: form-data; name=”f”; (表单项名称)filename=”a.jpg”(文件名)
Content-Type: mime类型如:image/pjpeg 消息体:文件数据
上传文件中遇到的问题
1、不能通过request.getParameter获取提交的参数
String name = request.getParameter("name");
String password = request.getParameter("password");
String zp = request.getParameter("f");
通过下面的方式可以获取全部的请求信息
public class MyServlet2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
ServletInputStream sl=req.getInputStream();
byte b[]=new byte[1024];
int len=0;
if((len=sl.read(b))!=-1){
System.out.println(new String(b,0,len));
}
}
}
2、中文路径乱码问题,路径重复问题,上传文件夹缓存问题
<body>
<h1>文件上传</h1>
<form action="${pageContext.request.contextPath}/MyServlet3" method="post" enctype="multipart/form-data">
用户名: <input type="text" name="name"><br>
密码 :<input type="password" name="password"><br>
图片上传: <input type="file" name="f"><br>
<input type="submit" value="提交">
</form>
</body>
java代码
public class MyServlet3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
int szieThreshode = 1000 * 1024;
// 缓存目录
File repository = new File("f://temp");
DiskFileItemFactory factory = new DiskFileItemFactory(szieThreshode,
repository);
ServletFileUpload fileUpLoad = new ServletFileUpload(factory);
// 设置文件编码问题,防止中文乱码;
fileUpLoad.setHeaderEncoding("utf-8");
try {
List<FileItem> fileItems = fileUpLoad.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {
// 普通表单项目
} else {
// 文件 表单项
String fileName = fileItem.getName();
int i = fileName.lastIndexOf("/");
if (i != 0) {
fileName = fileName.substring(i + 1);
}
fileName = UUID.randomUUID().toString().replace("-", "")
+ fileName;
int hashCode = fileName.hashCode();// 获取文件名的hashcode
String hex = Integer.toHexString(hashCode);// 转换十六进制
String path = hex.charAt(0) + "/" + hex.charAt(1);
// 封装存储目录为File对象
File dir = new File(this.getServletContext().getRealPath(
"/WEB-INF/upload" + "/" + path));
dir.mkdirs();// 创建目录
// 将文件存储在WebRoot/upload目录下
File file = new File(dir, fileName);
fileItem.write(file);
fileItem.delete();// 删除临时文件
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3、文件下载
文件下载,就是从服务器上的目标资源拷贝到本地
但浏览器类型不同,需要不同的对待,比如一个图片浏览器能够识别,就直接会打开,而不能识别的会提示下载
public class DownServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
String filename=req.getParameter("filename");
File file =new File(this.getServletContext().getRealPath("/down"),filename);
FileInputStream fis =new FileInputStream(file);
//获取文件类型;
String mimeType=this.getServletContext().getMimeType(filename);
//设置content-disposition
resp.setHeader("content-disposition", "attachment;filename"+filename);
IOUtils.copy(fis, resp.getOutputStream());
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(req, resp);
}
}