JSP中文件的上传于下载示例

一、文件上传的原理

1、文件上传的前提:

a、form表单的method必须是post

b、form表单的enctype必须是multipart/form-data(决定了POST请求方式,请求正文的数据类型)

注意:当表单的enctype是multipart/form-data,传统的获取请求参数的方法失效。

请求正文:(MIME协议进行描述的,正文是多部分组成的)

-----------------------------7dd32c39803b2

Content-Disposition: form-data; name="username"

wzhting

-----------------------------7dd32c39803b2

Content-Disposition: form-data; name="f1"; filename="C:\Documents and Settings\wzhting\妗岄潰\a.txt"

Content-Type: text/plain

aaaaaaaaaaaaaaaaaa

-----------------------------7dd32c39803b2

Content-Disposition: form-data; name="f2"; filename="C:\Documents and Settings\wzhting\妗岄潰\b.txt"

Content-Type: text/plain

bbbbbbbbbbbbbbbbbbb

-----------------------------7dd32c39803b2--

c、form中提供input的type是file类型的文件上传域

二、利用第三方组件实现文件上传

1、commons-fileupload组件:

jar:commons-fileupload.jar  commons-io.jar

2、核心类或接口

DiskFileItemFactory:设置环境

public void setSizeThreshold(int?sizeThreshold) :设置缓冲区大小。默认是10Kb。

当上传的文件超出了缓冲区大小,fileupload组件将使用临时文件缓存上传文件

public void setRepository(java.io.File repository):设置临时文件的存放目录。默认是系统的临时文件存放目录。

ServletFileUpload:核心上传类(主要作用:解析请求的正文内容)

boolean isMultipartContent(HttpServletRequest?request):判断用户的表单的enctype是否是multipart/form-data类型的。

List parseRequest(HttpServletRequest request):解析请求正文中的内容

setFileSizeMax(4*1024*1024);//设置单个上传文件的大小

upload.setSizeMax(6*1024*1024);//设置总文件大小

FileItem:代表表单中的一个输入域。

boolean isFormField():是否是普通字段

String getFieldName:获取普通字段的字段名

String getString():获取普通字段的值

InputStream getInputStream():获取上传字段的输入流

String getName():获取上传的文件名

三、文件上传中要注意的9个问题

1、如何保证服务器的安全

把保存上传文件的目录放到WEB-INF目录中。

2、中文乱码问题

2.1普通字段的中文请求参数

String value = FileItem.getString("UTF-8");

2.2上传的文件名是中文

解决办法:request.setCharacterEncoding("UTF-8");

3、重名文件被覆盖的问题

System.currentMillions()+"_"+a.txt(乐观)

UUID+"_"+a.txt:保证文件名唯一

4、分目录存储上传的文件

方式一:当前日期建立一个文件夹,当前上传的文件都放到此文件夹中。

方式二:利用文件名的hash码打散目录来存储。

int hashCode = fileName.hashCode();

1001 1010 1101 0010 1101 1100 1101 1010

hashCode&0xf;   0000 0000 0000 0000 0000 0000 0000 1111 &

---------------------------------------------

0000 0000 0000 0000 0000 0000 0000 1010   取hashCode的后4位

0000~1111:整数0~15共16个

1001 1010 1101 0010 1101 1100 1101 1010

(hashCode&0xf0)    0000 0000 0000 0000 0000 0000 1111 0000  &

--------------------------------------------

0000 0000 0000 0000 0000 0000 1101 0000  >>4

--------------------------------------------

0000 0000 0000 0000 0000 0000 0000 1101

0000~1111:整数0~15共16个

5、限制用户上传的文件类型

通过判断文件的扩展名来限制是不可取的。

通过判断其Mime类型才靠谱。FileItem.getContentType();

6、如何限制用户上传文件的大小

6.1单个文件大小限制。超出了大小友好提示

抓异常进行提示:org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException

6.2总文件大小限制。超出了大小友好提示

抓异常进行提示:org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException

7、临时文件的问题

commons-fileupload组件不会删除超出缓存的临时文件。

FileItem.delete()方法删除临时文件。但一定要在关闭流之后。

8、多个文件上传时,没有上传内容的问题

if(fileName==null||"".equals(fileName.trim())){

continue;

}

9、上传进度检测

给ServletFileUpload注册一个进度监听器即可,把上传进度传递给页面去显示

//pBytesRead:当前以读取到的字节数

//pContentLength:文件的长度

//pItems:第几项

public void update(long pBytesRead, long pContentLength,

int pItems) {

System.out.println("已读取:"+pBytesRead+",文件大小:"+pContentLength+",第几项:"+pItems);

}

四:文件上传示例:

JSP代码:

<form action="${pageContext.request.contextPath}/servlet/UploadServlet" method="post" enctype="multipart/form-data">
    	用户名:<input type="text" name="username"/><br/>
    	文件1:<input type="file" name="f1"/><br/>
    	文件2:<input type="file" name="f2"/><br/>
    	<input type="submit" value="保存"/>
    </form>

servlet后台代码:

public class UploadServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter pout = response.getWriter();
		try {
			// 得到存放上传文件的真实路径
			String storePath = getServletContext()
					.getRealPath("/WEB-INF/files");

			// 设置环境
			DiskFileItemFactory factory = new DiskFileItemFactory();
			factory.setRepository(new File(getServletContext().getRealPath("/temp")));//设置临时存放目录
			// 判断一下form是否是enctype=multipart/form-data类型的
			boolean isMultipart = ServletFileUpload.isMultipartContent(request);
			if (!isMultipart) {
				System.out.println("大傻鸟");
				return;
			}
			// ServletFileUpload核心类
			ServletFileUpload upload = new ServletFileUpload(factory);
//			upload.setProgressListener(new ProgressListener() {
//				//pBytesRead:当前以读取到的字节数
//				//pContentLength:文件的长度
//				//pItems:第几项
//				public void update(long pBytesRead, long pContentLength,
//						int pItems) {
//					System.out.println("已读取:"+pBytesRead+",文件大小:"+pContentLength+",第几项:"+pItems);
//				}
//
//			});
			upload.setFileSizeMax(4 * 1024 * 1024);// 设置单个上传文件的大小
			upload.setSizeMax(6 * 1024 * 1024);// 设置总文件大小
			// 解析
			List<FileItem> items = upload.parseRequest(request);
			for (FileItem item : items) {
				if (item.isFormField()) {
					// 普通字段
					String fieldName = item.getFieldName();
					String fieldValue = item.getString("UTF-8");
					System.out.println(fieldName + "=" + fieldValue);
				} else {
					// 得到MIME类型
					String mimeType = item.getContentType();
					// 只允许上传图片
					 if(mimeType.startsWith("image")){
						// 上传字段
						InputStream in = item.getInputStream();
						// 上传的文件名
						String fileName = item.getName();// C:\Documents and
						if(fileName==null||"".equals(fileName.trim())){
							continue;
						}
						// Settings\wzhting\妗岄潰\a.txt
						// a.txt
						fileName = fileName
								.substring(fileName.lastIndexOf("\\") + 1);// a.txt
						fileName = UUID.randomUUID() + "_" + fileName;
						System.out.println(request.getRemoteAddr()+"=============="+fileName);
						// 构建输出流
						// 打散存储目录
						String newStorePath = makeStorePath(storePath, fileName);// 根据
						// /WEB-INF/files和文件名,创建一个新的存储路径
						// /WEB-INF/files/1/12
						String storeFile = newStorePath + "\\" + fileName;// WEB-INF/files/1/2/sldfdslf.txt

						OutputStream out = new FileOutputStream(storeFile);

						byte b[] = new byte[1024];
						int len = -1;
						while ((len = in.read(b)) != -1) {
							out.write(b, 0, len);
						}
						out.close();
						in.close();
						item.delete();//删除临时文件
					}
				 }
			}
		} catch (org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException e) {
			// 单个文件超出大小时的异常
			pout.write("单个文件大小不能超出4M");
		} catch (org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException e) {
			// 总文件超出大小时的异常
			pout.write("总文件大小不能超出6M");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	// 根据 /WEB-INF/files和文件名,创建一个新的存储路径 /WEB-INF/files/1/12
	private String makeStorePath(String storePath, String fileName) {
		int hashCode = fileName.hashCode();
		int dir1 = hashCode & 0xf;// 0000~1111:整数0~15共16个
		int dir2 = (hashCode & 0xf0) >> 4;// 0000~1111:整数0~15共16个

		String path = storePath + "\\" + dir1 + "\\" + dir2; // WEB-INF/files/1/12
		File file = new File(path);
		if (!file.exists())
			file.mkdirs();

		return path;
	}

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

		doGet(request, response);
	}

}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

五:文件下载

1.显示上述存储所有的照片信息:

//显示所有上传的文件,封装到域对象中,交给jsp去显示
public class ShowAllFilesServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Map<String, String> map = new HashMap<String, String>();//key:UUID文件名;value:老文件名
		//得到存储文件的根目录
		String storePath = getServletContext().getRealPath("/WEB-INF/files");
		//递归遍历其中文件
		File file = new File(storePath);
		treeWalk(file,map);
		//交给JSP去显示:如何封装数据.用Map封装。key:UUID文件名;value:老文件名
		request.setAttribute("map", map);
		request.getRequestDispatcher("/listFiles.jsp").forward(request, response);
	}
	//遍历/WEB-INF/files所有文件,把文件名放到map中
	private void treeWalk(File file, Map<String, String> map) {
		if(file.isFile()){
			//是文件
			String uuidName = file.getName();//  UUID_a_a.txt//真实文件名
			String oldName = uuidName.substring(uuidName.indexOf("_")+1);
			map.put(uuidName, oldName);
		}else{
			//是一个目录
			File[] fs = file.listFiles();
			for(File f:fs){
				treeWalk(f,map);
			}
		}
	}

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

		doGet(request, response);
	}

}

2.显示所有文件listFiles.jsp页面中的内容:

<body>
    <h1>本站有以下好图片</h1>
    <c:forEach items="${map}" var="me">
    	<c:url value="/servlet/DownloadServlet" var="url">
    		<c:param name="filename" value="${me.key}"></c:param>
    	</c:url>
    	${me.value}  <a href="${url}">下载</a><br/>
    </c:forEach>
  </body>

3.文件下载DownloadServlet:

public class DownloadServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		OutputStream out = response.getOutputStream();

		String filename = request.getParameter("filename");//get请求方式
		filename = new String(filename.getBytes("ISO-8859-1"),"UTF-8");//中文编码

		//截取老文件名
		String oldFileName = filename.split("_")[1];
		//得到存储路径
		String storePath = getServletContext().getRealPath("/WEB-INF/files");
		//得到文件的全部路径
		String filePath = makeStorePath(storePath, filename)+"\\"+filename;

		//判断文件是否存在
		File file = new File(filePath);
		if(!file.exists()){
			out.write("对比起!你要下载的文件可能已经不存在了".getBytes("UTF-8"));
			return;
		}

		InputStream in = new FileInputStream(file);
		//通知客户端以下载的方式打开
		response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(oldFileName, "UTF-8"));

		byte[] b = new byte[1024];
		int len = -1;
		while((len=in.read(b))!=-1){
			out.write(b, 0, len);
		}
		in.close();
		out.write("下载成功".getBytes("UTF-8"));
	}

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

		doGet(request, response);
	}
	private String makeStorePath(String storePath, String fileName) {
		int hashCode = fileName.hashCode();
		int dir1 = hashCode & 0xf;// 0000~1111:整数0~15共16个
		int dir2 = (hashCode & 0xf0) >> 4;// 0000~1111:整数0~15共16个

		String path = storePath + "\\" + dir1 + "\\" + dir2; // WEB-INF/files/1/12
		File file = new File(path);
		if (!file.exists())
			file.mkdirs();

		return path;
	}
}

JSP中文件的上传于下载示例

时间: 2024-10-10 08:39:02

JSP中文件的上传于下载示例的相关文章

struts中文件的上传和下载

首先我们还是新建一个新的web project 取名为upload_test 然后在WebRoot中新建两个jsp页面 upload.jsp 和result.jsp 代码分别如下: upload.jsp Jsp代码   <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <% String path = request.getCont

iOS开发中文件的上传和下载功能的基本实现-备用

感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代码. 主控制器的关键代码: 复制代码代码如下: YYViewController.m#import "YYViewController.h" #define YYEnc

009 spring boot中文件的上传与下载

一:任务 1.任务 文件的上传 文件的下载 二:文件的上传 1.新建一个对象 FileInfo.java 1 package com.cao.dto; 2 3 public class FileInfo { 4 private String path; 5 public FileInfo(String path) { 6 this.path=path; 7 } 8 public String getPath() { 9 return path; 10 } 11 public void setPa

如何在Linux中使用sFTP上传或下载文件与文件夹

如何在Linux中使用sFTP上传或下载文件与文件夹 sFTP(安全文件传输程序)是一种安全的交互式文件传输程序,其工作方式与 FTP(文件传输协议)类似. 然而,sFTP 比 FTP 更安全;它通过加密 SSH 传输处理所有操作.在本文中,我们将向你展示如何使用 sFTP 上传/下载整个目录(包括其子目录和子文件). 作者:Aaron Kili来源:Linux中国|2017-03-09 14:42 移动端 收藏 分享 51CTO诚邀您9月23号和秒拍/国美/美团元专家一起聊智能CDN的优化之路

SpringMVC实现文件的上传和下载

前些天一位江苏经贸的学弟跟我留言问了我这样一个问题:"用什么技术来实现一般网页上文件的上传和下载?是框架还是Java中的IO流".我回复他说:"使用SpringMVC框架可以做到这一点,因为SpringMVC为文件的上传提供了直接的支持,但需要依赖Apache提供Commons FileUpload组件jar包."鉴于这个问题,我上网也百度了一下,网上很多都是介绍的使用IO流来实现文件的上传和下载,也有说到框架的,但介绍的并不是很完整,今天小钱将和大家介绍使用Spr

在SpringMVC框架下实现文件的 上传和 下载

在eclipse中的javaEE环境下:导入必要的架包 web.xml的配置文件: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation=&

Java Web总结十八文件的上传和下载

一.实现Web开发中的文件上传功能,需完成如下两步操作: 1.在web页面中添加上传输入项. 2.在Servlet中读取上传文件的数据,并保存到本地硬盘中. 二.如何在web页面中添加上传输入项? 1.<input type="file">标签用于在web页面中添加文件上传输入项,设置文件上传输入项时须注意: 1)必须设置input输入项的name属性,否则浏览器将不会发送上传文件的数据. 2)必须把form的enctype属性值设为multipart/form-data.

Servlet方式实现文件的上传和下载

文件的上传和下载需要两个jar包  commons-fileupload-1.2.2.jar和commons-io-2.0.1.jar JSP页面 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Trans

Spring MVC 实现文件的上传和下载

文件上传是项目开发中最常见的功能.为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data.只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器. 一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应.在2003年,Apache Software Foundation发布了开源的Commons File