文件上传
什么是文件上传:
将本地文件通过流写到服务器上。
文件上传的要素:
1. 表单提交的方式必须是POST。
2. 表单中必须有<input type=”file” >而且这元素必须有name属性和值。
3. 表单的enctype属性的值必须设置为multipart/form-data
我们可以发现没有设置enctype的时候,这个时候请求头中只有文件的名称,没有文件内容。
所以,设置enctype是为了让请求头中能够显示文件的内容。
文件上传代码实现:
1.0上传的页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>文件上传</h1>
<!--
表单提交的方式必须是POST。
表单中必须有<input type=”file” >而且这元素必须有name属性和值。
表单的enctype属性的值必须设置为multipart/form-data
-->
<form action="${ pageContext.request.contextPath }/UploadServlet" method="post" enctype="multipart/form-data">
文件描述:<input type="text" name="desc"/><br/>
文件上传:<input type="file" name="upload"/><br/>
<input type="submit" value="上传">
</form>
</body>
</html>
2.0创建相关的工具类:
package com.itheima.utils;
import java.util.UUID;
public class FileUploadUtils {
/*
* 获得唯一文件名的方法;
*/
public static String getUUIDFilename(String filename) {
//将随机生成的字符串中的- 替换掉。
String name = UUID.randomUUID().toString().replace("-", "");
//获得文件的扩展名;
int indexOf = filename.indexOf(".");
String substring = filename.substring(indexOf);
return name+substring;
}
/*
* 获得目录分离的方法;
*/
public static String getPath(String uuidFilename) {
//获得转换后的唯一文件名的hashCode;
int hashCode = uuidFilename.hashCode();
//将这个值 &0xf
int d1=hashCode & 0xf;
//让hashCode值右移4位:
int hashCode2=hashCode >>>4;
//将这个值 &0xf
int d2=hashCode2 & 0xf;
//这里就分离为两级目录
return "/"+d1+"/"+d2;
}
}
3.0创建相关的UploadServlet类:
package com.itheima.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import com.itheima.utils.FileUploadUtils;
/**
* Servlet implementation class UploadServlet
*/
@WebServlet("/UploadServlet")
@MultipartConfig
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//接收参数:
String parameter = request.getParameter("desc");
//获得文件上传总的文件的相关的信息:
//Part代表的是文件上传的部分。
Part part = request.getPart("upload");
//获得文件大小:
long size = part.getSize();
System.out.println("文件大小:"+size);
//获得文件的类型:
String contentType = part.getContentType();
System.out.println("文件的类型:"+contentType);
//获得提交的文件标签中的name属性值:
String name = part.getName();
System.out.println("name的属性值:"+name);
//获得文件名字:
String header = part.getHeader("Content-Disposition");
int lastIndexOf = header.lastIndexOf("filename=\"");
String substring = header.substring("filename=\"".length()+lastIndexOf, header.length()-1);
if(substring.indexOf("\\") != -1) {
//说明是ie浏览器
int lastIndexOf2 = substring.lastIndexOf("\\");
substring = substring.substring(lastIndexOf2+1,substring.length() );
}
System.out.println("文件名称是:"+substring);
//获得上传文件的输入流:
InputStream inputStream = part.getInputStream();
//获得上传文件的路径:
String realPath = this.getServletContext().getRealPath("/upload");
//先获得唯一的文件名:
String uuidFilename = FileUploadUtils.getUUIDFilename(substring);
//创建输出流:
//获得目录分离后的绝对路径
String path = FileUploadUtils.getPath(uuidFilename);
String realPath2=realPath+path;
File file=new File(realPath2);
if(! file.exists()) {
file.mkdirs();
}
OutputStream os=new FileOutputStream(realPath2+"/"+uuidFilename);
int len=0;
byte[] arr=new byte[1024];
while((len=inputStream.read(arr)) != -1) {
os.write(arr, 0, len);
}
inputStream.close();
os.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
文件上传中的问题:
1.0上传文件名是中文的问题:
就是将中文名转换为唯一的随机字符串文件名进行处理。
2.0文件重名问题:
也是通过将文件名转化为唯一的随机字符串来处理这个问题。
3.0一个目录下存放的文件过多问题:
一个目录下文件过多导致打开都很慢,更别说读写文件。
问题解决方法:按算法分:按照某种目录分离算法进行目录分离。(代码实现在工具类中)