13上传 下载

Posted 重庆刘亦菲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了13上传 下载相关的知识,希望对你有一定的参考价值。

**文件上传的概述**
	
	1.了解什么是文件上传
	2.文件上传需要大家记住编写客户端需要有3个注意事项。
	3.什么是文件上传
		* 把本地的文件保存到服务器端
	
	4.做文件上传,该怎么做?
		* 客户端
			* 选择一个要上传的文件
			* 需要提供文件的选择输入框(<input type="file">)
			* 注意:如果完成文件的上传,必须有3点注意事项的
				* 编写表单,method="post" 必须是post
				* 表单中还有一个属性,enctype="multipart/form-data"
				* 编写文件的选项框	<input type="file" name="必须要指定,名称可以任意">
		
		* 服务器端
			* 把上传的文件写入到某个指定的文件夹下

![](./图片/01-文件上传的概述.bmp)	
	
----------
	
**Fileupload文件上传的组件**
	
	1.由apache提供的开源的jar包
		* 导入开发的jar包
			* commons-fileupload-1.2.1.jar
			* commons-io-1.4.jar
	
	2.入门的开发
		* 开发的步骤,开发的步骤比较固定
	
![](./图片/02-FileUpload开发的流程.bmp)	
	
----------
	
**文件上传入门案例**
	
	1.编写入门的案例,目的:让大家来熟悉开发的步骤,使用一些对象和方法,后面讲解。
	2.文件上传的案例步骤
		* 客户端
			* 注意3个注意事项		
		
		* 服务器端
			* 采用的是FileUpload文件上传的组件,不要忘记导入开发的jar包。
			* 创建工厂类,生成对象
			* 创建核心解析类,解析request请求,获取到文件项(FileItem)
			* 操作FileItem类的方法就可以完成文件的上传了
	
----------
	
### FileUpload组件的类和方法 ###
	
----------
	
**DiskFileItemFactory类**
	
	1.DiskFileItemFactory:代表磁盘文件项工厂类,作用:用来生产FileItem对象的。
	2.方法
		* DiskFileItemFactory()					-- 空的构造经常使用的。
		
		* DiskFileItemFactory(int sizeThreshold, java.io.File repository)	
			* sizeThreshold		-- 设置上传文件的缓冲区的大小,如果不指定,有默认值是10K
			* repository		-- 设置临时文件的存储目录,如果上传的文件,超过了缓冲区的大小,产生临时文件,设置临时文件存储的目录。
		
		* void setSizeThreshold(int sizeThreshold)			-- 设置缓冲区的大小
		* void setRepository(java.io.File repository)		-- 设置临时文件的存储目录(上传的文件超过了缓冲区的大小,产生临时文件)
	
	3.总结
		* 上述的这两个方法,如果不设置都有默认值的。
	
----------
	
**ServletFileUpload类(解析request)**
	
	1.ServletFileUplod	代表的文件上传的类,作用:用来解析request请求。
	2.方法
		* ServletFileUpload(FileItemFactory fileItemFactory)
		* static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request)		-- 判断表单的enctype值设置的是否正确
		* java.util.List parseRequest(javax.servlet.http.HttpServletRequest request)			-- 解析request请求,返回的是List集合
		* void setHeaderEncoding(java.lang.String encoding)										-- 解决中文文件名称乱码的问题。
		* void setFileSizeMax(long fileSizeMax)													-- 设置单个上传文件的大小
		* void setSizeMax(long sizeMax)															-- 设置总大小
	
	3.总结(掌握)
		* parseRequest(request)		-- 解析request请求
		* setHeaderEncoding()		-- 解决中文乱码问题呢
		* setSizeMax()				-- 设置上传文件的总大小	
		* void setFileSizeMax()
	
----------
	
**FileItem接口(文件项)**
	
	1.FileItem类:代表文件项(普通表单项(文本框、密码、单选),又有可能文件的上传项)
	2.方法
		* boolean isFormField()	
			* 判断当前的fileItem对象是否是普通表单项还是文件上传项?如果返回true,说明是普通表单项,如果是false,是文件上传项
		
		* 如果是普通表单项(文本框 密码框 复选框 单选框 下拉列表)
			* java.lang.String getFieldName()					-- 获取的表单中的name属性的值(例如:filedesc)
			* java.lang.String getString()						-- 获取到用户输入的值(没有解决乱码的问题)
			* java.lang.String getString(String encoding)		-- 获取到用户输入的值(解决中文乱码问题)
		
		* 如果是文件上传项
			* java.lang.String getName()						-- 获取的上传文件的名称(ServletFileUpload类中setHeaderEncoding()解决中文乱码)
			* java.io.InputStream getInputStream()				-- 获取到上传文件的输入流
			* void write(java.io.File file)						-- 直接写入文件
			* void delete()										-- 删除临时文件的(注意:删除的代码需要放在流关闭之后)
	
	3.总结
		* 上述所有	
	
----------
	
**文件上传存在的问题**
	
	1.第一个问题:如果使用的是IE6浏览器,存在问题。
		* 如果是IE6的浏览器,获取的文件的名称是:C:\class\resource\hello.txt
		
		* 如果浏览器是IE的一些版本(IE6肯定存在该问题),如果使用的是IE6版本的浏览器,选择文件的时候,选择完文件,点击上传。
		* 在Servlet中获取到的文件名称是包含文件的路径的。
	
	2.第二个问题:request.getParameter()方法已经不能获取到表单的内容了。(重要的)
		* 使用request对象的时候,request.getParameter()方法,在文件上传中,使用的enctype="multipart/form-data"方式,那么request.getParameter()获取不到值了。
	
	3,注意;	request.getParameter()已经不能获取到值了!!!

upload.jsp:

<%@ 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>

<h3>文件的上传</h3>

<form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data">
	文件描述:<input type="text" name="filedesc"/><br/>
	文件上传:<input type="file" name="upload"/><br/>
	<input type="submit" value="上传"/>
</form>
</body>
</html>

UploadServlet:

public class UploadServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/**
		 * 1.创建一个工厂类
		 * 2.创建能解析request对象的类
		 * 3.解析request请求
		 * 4.返回的是List集合
		 * 5.遍历集合,获取到每一个FileItem
		 * 6.操作FileItem中方法完成文件的上传
		 */
		//判断,表单的enctype属性值是否设置正确,返回true,说明设置正确。返回false,不正确
		if(!ServletFileUpload.isMultipartContent(request)){
			//说明设置不正确
			throw new RuntimeException("亲,您没有设置正确的enctype属性的值");
		}
		
		
		//1.创建工厂类
		DiskFileItemFactory factory=new DiskFileItemFactory();
		
		//设置缓冲区的大小 设置2M
		factory.setSizeThreshold(2*1024*1024);
		//设置临时文件的存储目录
		String tempPath=this.getServletContext().getRealPath("/temp");
		System.out.println(tempPath);
		//创建文件目录
		File tempFile=new File(tempPath);
		
		factory.setRepository(tempFile);
		
		//2.创建能解析request对象的类
		ServletFileUpload upload=new ServletFileUpload(factory);
		
		//设置头的编码,解决中文文件名称乱码的问题
		upload.setHeaderEncoding("utf-8");
		//设置文件上传的总大小 4M
		upload.setSizeMax(4*1024*1024);
		
		try {
			//3.解析request请求
			//4.返回的是List集合
			List<FileItem> list=upload.parseRequest(request);
			//5.遍历集合,获取到每一个FileItem
			for (FileItem fileItem : list) {
				//需要判断,当前的fileItem是否是文件描述还是文件上传
				//isFormField(),返回true,说明表单的字段(text,password,checkbox,radio)
				if(fileItem.isFormField()){
					
					//获取表单中name属性的值
					String name=fileItem.getFieldName();
					
					//文件描述,获取用户输入的值
					String value= fileItem.getString();
					String value_=fileItem.getString("UTF-8");
					
					System.out.println(name+":::"+value+value_);
					
				}else{
					//返回false,说明type="file" 说明是文件上传,需要获取用户上传的文件的文件名称
					String fileName=fileItem.getName();
					
					//生成唯一的文件的名称
					String uuid=UUID.randomUUID().toString();
					//名称完全换掉hello.txt --> ffggerwefd.txt
					int i=fileName.lastIndexOf(".");
					//文件的后缀名
					String lastName=fileName.substring(i);
					String uuidName=uuid+"_"+lastName;
					
					//获取到的是文件的输入流
					InputStream in=fileItem.getInputStream();
					
					//获取upload文件夹的绝对路径
					String path=this.getServletContext().getRealPath("/upload");
					System.out.println("upload文件夹的绝对路径:"+path);
					//创建输出流
					OutputStream out=new FileOutputStream(path+"/"+uuidName);
					byte[] by=new byte[1024];
					int len=0;
					while((len=in.read(by))!=-1){
						out.write(by, 0 ,len);
					}
					out.close();
					in.close();
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		}
		
	}

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

 

**多文件上传(js控制多个上传输入项)**
	
	1.多文件上传
		* 需求:点击添加按钮,生成多个文件的上传项。点击删除的按钮,删除该个上传项。点击上传按钮,把选择的所有的文件上传到服务器端。
		* 前台和后台

moreupload.jsp:

<%@ 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>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.8.3.js"></script>
<script type="text/javascript">
	$(function(){
		$("input[type=‘button‘]").click(function(){
			
			//创建div
			var $div=$("<div></div>");
			
			//创建选择框
			var $input=$("<input type=‘file‘ name=‘upload‘/>");
			var $del=$("<input type=‘button‘ value=‘删除‘/><br/>");
			
			//给删除按钮绑定事件
			$del.click(function(){
				//删除一行,小div
				$(this).parent().remove();
			});
			
			$div.append($input);
			$div.append($del);
			
			//生成的小div存入大的div
			$("#divId").append($div);
		});
		
	});
</script>
</head>
<body>

<h3>多文件的上传</h3>
<form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data">
	<input type="button" value="添加" />
	<input type="submit" value="上传"/>
	
	<!-- div,存放生成文件的选择项 -->
	<div id="divId"></div>
</form>
</body>
</html>

  

案例:上传图书封面

AddServlet:

/**
 * 添加商品(包含文件的上传)
 * @author mjl
 *
 */
public class AddProduct extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		DiskFileItemFactory factory=new DiskFileItemFactory();
		ServletFileUpload upload=new ServletFileUpload(factory);
		//解决中文文件名称乱码问题
		upload.setHeaderEncoding("utf-8");
		
		//创建一个Map,存入用户输入的值
		Map<String,String> map=new HashMap();
		Product product=new Product();
		String uuidName=null;
		try {
			List<FileItem> list = upload.parseRequest(request);
			for (FileItem fileItem : list) {
				if(fileItem.isFormField()){
					//获取到每个表单项的name的值
					String name=fileItem.getFieldName();
					//获取到用户输入的值
					String value=fileItem.getString("utf-8");
					//存入到map集合  map: pname 故事会  price 10
					map.put(name, value);
					
				}else{
					String fileName=fileItem.getName();
					if(fileName!=null && !fileName.trim().isEmpty()){
						
						String uuid=MyUUIDUtils.getUUID();
						int i=fileName.lastIndexOf(".");
						String lastName=fileName.substring(i);
						//唯一的文件名称
						uuidName=uuid+lastName;
						
						InputStream in=fileItem.getInputStream();
						
						String path=this.getServletContext().getRealPath("/bookcover");
						System.out.println(path);
						OutputStream out=new FileOutputStream(path+"/"+uuidName);
						int len=0;
						byte[] by=new byte[1024];
						while((len=in.read(by))!=-1){
							out.write(by, 0, len);
						}
						out.close();
						in.close();
						fileItem.delete();
					}
				}
			}			
			//使用BeanUtils来封装数据
			BeanUtils.populate(product, map);
			product.setImgUrl(uuidName);
			
			ProductService ps=new ProductService();
			ps.save(product);
			
			//如果添加成功了,跳转查询所有商品的方法
			response.sendRedirect(request.getContextPath()+"/product?method=findAll");
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

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

 

文件下载:

download.jsp:

<%@ 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>

<h3>文件下载的页面</h3>
<h4><a href="${pageContext.request.contextPath }/download?filename=大二.jpg">大二.jpg</a></h4>
<h4><a href="${pageContext.request.contextPath }/download?filename=guoguo.jpg">guoguo.jpg</a></h4>
<h4><a href="${pageContext.request.contextPath }/download?filename=wangwang.txt">wangwang.txt</a></h4>

</body>
</html>

DownloadServlet:

/**
 * 文件的下载
 * @author mjl
 *
 */
public class DownloadServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//先获取文件的名称
		String filename=request.getParameter("filename");
		
		//两个头(响应头),一个流(文件的输入流)
		//content-Type 代表要下载文件的MIME的类型    txt=text/plain jpg=image/jpeg
		//response.senContentType("text/html;charset=utf-8");
		String mimeType=getServletContext().getMimeType(filename);
		System.out.println("文件的MIME类型:"+mimeType);
		response.setContentType(mimeType);
		
		//弹出下载的窗口 Content-Disposition 值 attachment;filenmae=加上文件名称
		response.setHeader("Content-Disposition", "attachment;filename="+filename);
		
		
		//获取download的路径
		String path=this.getServletContext().getRealPath("/download");
		InputStream in=new FileInputStream(path+"/"+filename);
		//使用response对象,响应
		OutputStream out=response.getOutputStream();
		byte[] by=new byte[1024];
		int len=0;
		while((len=in.read(by))!=-1){
			out.write(by,0,len);
		}
	}

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

	}
}

  

以上是关于13上传 下载的主要内容,如果未能解决你的问题,请参考以下文章

大文件上传下载实现思路,分片断点续传代码实现,以及webUpload组件

VSCode自定义代码片段13——Vue的状态大管家

VSCode自定义代码片段13——Vue的状态大管家

VSCode自定义代码片段13——Vue的状态大管家

Android - 应用程序启动时片段 onCreate 崩溃

java Ftp上传创建多层文件的代码片段