文件上传
文件上传
1. 文件上传的服务器简单实现
1.解压,把jar包复制到项目中。
核心类:DiskFileItemFactory 创建一个用于接受文件上传其他组件的工厂类。
ServletFileUpload 它是真正可以接受Servlet中上传的文件的。
FileItem 它是在上传中的每一个子项
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1 创建工厂类
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
// 2 创建解析文件的核心类
ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
try {
// 3 解析请求 获得表单项集合
List<FileItem> fileitems = fileUpload.parseRequest(request);
// 4 遍历集合
for (FileItem fileItem : fileitems) {
if (fileItem.isFormField()) {
// 4.1 如果是普通表单项: name属性值 和 用户填写或者选择的值
String name = fileItem.getFieldName(); // name属性值
String val = fileItem.getString("utf-8"); // 用户填写或者选择的值
System.out.println("普通表单项:" + name + "=" + val);
} else {
// 4.2 如果是文件上传项: 获得文件的输入流 ,文件名,name属性值
String filename = fileItem.getName(); // 文件名
String name = fileItem.getFieldName();// name属性值
// 文件目录对象
File path = new File(this.getServletContext().getRealPath("/upload"));
path.mkdirs();
// 文件对象
File file = new File(path, filename);
InputStream in = new BufferedInputStream(fileItem.getInputStream());
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
in.close();
out.close();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("上传成功!" + (new Date()).toLocaleString());
}
2.多文件上传
2.1. 浏览器端js实现
<script type="text/javascript">
// 页面加载完成后执行
window.onload = function(){
// 给添加附件的按钮绑定单击事件
$("addAttachment").onclick = function(){
// 1 添加div标签对象
var _div = document.createElement("div"); // <div></div>
// 3 增加文件上传的input标签 将input标签追加到div中
var _input = document.createElement("input"); // <input/>
_input.setAttribute("type", "file");// <input type="file"/>
_input.setAttribute("name", "upload");// <input type="file" name="upload"/>
_div.appendChild(_input); // <div><input type="file" name="upload"/></div>
// 4 增加删除的超链接 追加到div中
var _a = document.createElement("a"); // <a></a>
_a.setAttribute("href", "javascript:void(0)"); // <a href="javascript:void(0)"></a>
_a.innerHTML = "删除"; // <a href="javascript:void(0)">删除</a>
_div.appendChild(_a); // <div><input type="file" name="upload"/><a href="javascript:void(0)">删除</a></div>
// 5 给新增的超链接 绑定单击事件 删除div标签
_a.onclick = function(){
// 被删除的标签对象.父节点对象.removeChild(被删除的标签对象);
_div.parentNode.removeChild(_div);
}
// 2 将div追加到 id=uploaddiv的标签中
$("uploaddiv").appendChild(_div);
}
}
function $(_id) {
return document.getElementById(_id);
}
</script>
</head>
<body>
<input type="button" id="addAttachment" value="添加附件"/>
<form action="/day17/upload2" method="post" enctype="multipart/form-data">
<div id="uploaddiv">
</div>
<input type="submit" value="开始上传"/>
</form>
</body>
</html>
2.1. 文件上传问题-文件重名
2.2.1. 重名问题分析
在客户端可以多次给服务器上传同一个文件。这时就会发生文件的覆盖。这时我们就需要解决重名问题
我们使用的FileOutputStream在输出上传的文件数据,由于在输出的时候,使用的是上传的文件的名字,这样在服务器端给服务器本地指定的目录下保存的时候,同个目录下只能保存一个同名的文件。后续的全部被覆盖。
2.2.2. 重名问题解决方案
1、同名的文件,可以在文件名的后面(数字) ,应付少量的文件
2、文件一旦多了,这时就不能在同一个目录下保存。
2.1、一个用户一个目录,重名,可以使用UUID针对当前这个文件产生一个唯一的文件名,这样就可以保
证任何文件不重名,这样可以保证文件名永远唯一。
2.2、解决一个目录下文件过多的问题:
可以按照天来建文件的目录。
根据用户上传的每个文件信息,使用哈希算法,算出这个文件的唯一保存目录。
2.2.3. 目录分离方案解决(目录打散)