Eclipse16:文件的上传

这篇博客详细介绍了文件上传的概念、应用、技术、要素和原理,包括JSPSmartUpload、FileUpload、Servlet3.0和Struts2等文件上传组件。分析了enctype属性的重要性,讲解了文件上传的API,如DiskFileItemFactory、ServletFileUpload和FileItem的使用,并探讨了文件上传过程中遇到的浏览器兼容性、同名文件和目录过多等问题及其解决方案。
摘要由CSDN通过智能技术生成

一、概述

文件上传:将本地的文件通过流写入到服务器的过程

二、应用

  1. 实际开发中有很多应用:
    1. QQ空间上传图片
    2. 招聘网站上传简历

三、文件上传的技术

  1. JSPSmartUpload        :应用在JSP上的文件上传和下载的组件。
  2. FileUpload                   :应用在Java环境上的文件上传的功能。
  3. Servlet3.0                    :提供文件上传的功能
  4. Struts2                         :提供文件上传的功能

四、文件上传的要素

  1. 文件上传的三个要素
    1. 表单的提交的方式需要是POST(get方式有大小限制)
    2. 表单中需要有<input type=”file”>元素,需要有name属性和值。
    3. 表单enctype=”multipart/form-data”

五、文件上传的原理分析

5.1 加enctype与不加的区别

新建jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="" method="post" enctype="multipart/form-data">
		文件描述:<input type="text" name="miaoshu"><br>
		文件上传:<input type="file" name="upload"><br>
		<input type="submit" value="提交"><br>
	</form>
</body>
</html>

没设置enctype时候的请求部分:只有描述和上传的文件名 ,没有文件上传中的文件的具体的内容

设置enctype后:可看到文件内容

 5.2 文件上传原理分析

六、文件上传的入门

第一步:引入文件上传的相关的jar包

第二步:编写文件上传的页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="${pagecontext.request.contextPath}/uploadServlet" method="post" enctype="multipart/form-data">
		文件描述:<input type="text" name="miaoshu"><br>
		文件上传:<input type="file" name="upload"><br>
		<input type="submit" value="提交"><br>
	</form>
</body>
</html>

 第三步:编写文件上传的Servlet

第四步:访问http://localhost/demo7/jsp/upload.jsp,已上传成功。本地工程下无,需要到Tomcat目录下找 

注意:中间执行时报错,发现需要额外引入commons-io包

七、文件上传的API

7.1 DiskFileItemFactory:磁盘文件项工厂

构造方法

  1. DiskFileItemFactory()
  2. DiskFileItemFactory(int sizeThreshold,File repostory)
    1. sizeThreshold :设置文件上传的缓冲区的大小,默认值为10kb。
    2. repository  :设置文件上传过程中产生临时文件存放的路径 

API使用的代码

 注:超过缓冲区大小则会产生临时文件。

7.2 ServletFileUpload:核心解析类

 构造方法:

ServeltFileUpload(FileItemFactory fileItemFactory)

方法:

是用来判断表单的enctype属性是否正确。

 解析Request对象,返回一个List集合(每个部分的对象FileItem)

设置单个文件的大小

  设置上传的文件的总大小

设置中文文件名上传的乱码的问题。

 设置监听文件上传的进度

 7.3 FileItem文件项

方法:

判断表单项是普通项还是文件上传项。如果为true代表是普通项

 普通项的方法:

  1. 获得普通项的名称

      2.获得普通项的值

 文件上传项的方法:

1.获得文件上传的文件名的方法

2.获得文件上传的文件内容的方法

 3.获得文件上传的文件的大小

4.删除文件上传过程中的临时文件

7.4 JS控制多文件上传

案例需求

案例实现:

 

upload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
	function add(){
		console.log("add");
		//获得id为div1的元素
		var div1Element = document.getElementById("div1");
		div1Element.innerHTML += "<div><input type='file' name='upload'/><input type='button' value='删除' onclick='del(this)'/></div>";
	}
	function del(who){
		//who代表的是删除按钮,找到删除按钮的爷爷节点,并删除其子节点。
		who.parentNode.parentNode.removeChild(who.parentNode);
	}
</script>
</head>
<body>
<h1>多文件上传</h1>
<form action="${pageContext.request.contextPath}/uploadServlet" method="post" enctype="multipart/form-data">
	<input type="button" value="添加" onclick="add()"/>
	<input type="submit" value="上传"/><br>
	<div id="div1">
	</div>
</form>
</body>
</html>

 uploadSevlet.java

package com.itheima.upload;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


// 此处注意包的引用,为commons,不是tomcat
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;





/**
 * Servlet implementation class uploadServlet
 */
@WebServlet("/uploadServlet")
public class uploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
		DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
		ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
		List<FileItem> list = servletFileUpload.parseRequest(request);
		for(FileItem item:list) {
			if(item.isFormField()) {
				String fieldName = item.getFieldName();
				String value = item.getString("UTF-8");
				System.out.println(fieldName+" "+value);
			}else {
				String name = item.getName();
				InputStream inputStream = item.getInputStream();
				String realPath = getServletContext().getRealPath("/upload");
				FileOutputStream fileOutputStream = new FileOutputStream(realPath+"/"+name);
				int len=0;
				byte[] b = new byte[1024];
				while((len = inputStream.read()) != -1) {
					fileOutputStream.write(b, 0, len);
				}
				inputStream.close();
				fileOutputStream.close();
			}
		}
		
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 此处代码出现问题,解决方法2个:

(1)引入jar包

(2)导包不对,应该是common,而不是tomcat

7.5 文件上传兼容浏览器问题及解决

7.5.1 问题描述

如果使用IE老版本的浏览器出现一个文件名称获取错误问题。IE老版本获取文件名称的时候,会带有路径

7.5.2 问题解决

 7.7 文件上传同一个目录下文件同名的问题及解决

 7.7.1 问题描述

张三向服务器上传了一个文件aa.txt内容是hello world。李四向服务器上传了一个文件aa.txt内容hello Java。后上传的文件将先上传的文件覆盖

7.7.2 解决办法

UUID:和时间等有关,唯一标识码

用法:步骤一:新建UploadUtils工具类

 步骤二:Servlet中修改如下

7.8 文件上传同一个目录下存放文件过多的问题及解决

7.8.1 问题描述

现在所有的用户都上传文件,如果网站访问量比较大,如果都上传到同一个目录下,在同一个目录下存放的文件太多了,也会对程序有影响(其实打开该目录的时候,都会很卡,更别说读写操作)

7.8.2 问题解决

  1. 目录分离
    1. 按时间分离              :按月、周、天、小时。
    2. 按用户分离              :按张三、李四。
    3. 按个数分离              :一个目录下存放3000个文件。
    4. 按目录分离算法    :按照某种特定算法进行分离。
      1. 上传一个文件,得到一个唯一的文件名。
      2. 唯一文件名获取其hashCode值。-----int类型的值(32位)
      3. hashCode的值 & 0xf;-----得出的这个值作为一级目录。
      4. hashCode右移4  & 0xf;----得出的这个值作为二级目录。
      5. 以此类推。

算法实现:

步骤一:目录工具类

步骤二:Servlet

 

package com.itheima.upload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.itheima.utils.getPath;
import com.itheima.utils.getUuid;



/**
 * Servlet implementation class uploadServlet
 */
@WebServlet("/uploadServlet")
public class uploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
		DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
		ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
		List<FileItem> list = servletFileUpload.parseRequest(request);
		for(FileItem item:list) {
			if(item.isFormField()) {
				String fieldName = item.getFieldName();
				String value = item.getString("UTF-8");
				System.out.println(fieldName+" "+value);
			}else {
				String filename = item.getName();
				System.out.println("获取到的原始文件名:"+filename);
				//第一个\为转义字符				
				int lastIndexOf = filename.lastIndexOf("\\");
				if(lastIndexOf != -1) {
//					使用老版IE浏览器
					filename = filename.substring(lastIndexOf+1);
					System.out.println("对于老版IE浏览器处理后的文件名:"+filename);
				}
				String name = getUuid.getUuid(filename);
				System.out.println("UUID处理后的文件名:"+name);
				InputStream inputStream = item.getInputStream();
				String realPath = getServletContext().getRealPath("/upload");
				// 创建目录
				String path = getPath.getRealPath(name);
				realPath += path;
				File file = new File(realPath);
				System.out.println("上传路径:"+realPath);
//			目录不存在,则创建
				if(!file.exists()) {
					file.mkdirs();
				}

				FileOutputStream fileOutputStream = new FileOutputStream(realPath+"/"+name);
				int len=0;
				byte[] b = new byte[1024];
				while((len = inputStream.read()) != -1) {
					fileOutputStream.write(b, 0, len);
				}
				inputStream.close();
				fileOutputStream.close();
			}
		}
		
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值