文件上传和下载

1.文件上传的前提

提供form表单,method必须是post

form表单的enctype必须是multipart/form-data(enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码,multipart/form-data表示不对字符编码,在使用包含文件上传控件的表单时,必须使用该值)

提供input type="file"类的上传输入域

2.借助第三方上传组件fileupload实现上传

两个jar包:

在服务器端   

 1.创建DiskFileItemFactory     

2.创建ServletFileUpload   

 3.通过ServletFileUpload的parseRequest方法得到所有的FileItem

FileItem对象对应一个表单项(表单字段)。可以是文件字段或普通字段

  1. boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
  2. String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username;
  3. String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
  4. String getName():获取文件字段的文件名称;(a.txt)
  5. String getContentType():获取上传的文件的MIME类型,例如:text/plain。
  6. int getSize():获取上传文件的大小;
  7. InputStream getInputStream():获取上传文件对应的输入流;
  8. void write(File):把上传的文件保存到指定文件中。
  9. delete();

文件上传时要考虑的几个问题

a、保证服务器的安全

把保存上传文件的目录放在用户直接访问不到的地方。

 

b、避免文件被覆盖

让文件名唯一即可

c、避免同一个文件夹中的文件过多

方案一:按照日期进行打散存储目录

方案二:用文件名的hashCode计算打散的存储目录:二级目录

d、限制文件的大小:web方式不适合上传大的文件

单个文件大小:

ServletFileUpload.setFileSizeMax(字节)

总文件大小:(多文件上传)

ServletFileUpload.setSizeMax(字节)

e、上传字段用户没有上传的问题

通过判断文件名是否为空即可

f、临时文件的问题

DiskFileItemFactory:

作用:产生FileItem对象

内部有一个缓存,缓存大小默认是10Kb。如果上传的文件超过10Kb,用磁盘作为缓存。

存放缓存文件的目录在哪里?默认是系统的临时目录。

如果自己用IO流实现的文件上传,要在流关闭后,清理临时文件。

FileItem.delete();

文件上传demo

package com.shenhesoft.web.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
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.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;

public class UploadServlet extends HttpServlet {
	/**
	 * 文件上传的步骤
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		// 1.创建工厂类DiskFileItemFactory对象
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 2.使用工厂创建解析器对象
		ServletFileUpload upload = new ServletFileUpload(factory);

		// 解决中文乱码问题
		upload.setHeaderEncoding("UTF-8");

		try {
			// 设置上传文件的大小
			upload.setFileSizeMax(1024 * 1024 * 3);// 上传的文件不得超过3M
			// 上传文件的总大小
			// upload.setSizeMax(1024 * 1024 * 6);

			// 3.使用解析器来解析request对象

			List<FileItem> fileItems = upload.parseRequest(request);
			// 遍历表单项数据
			for (FileItem fileItem : fileItems) {
				// 判断是否是普通表单项,还是上传表单项
				if (fileItem.isFormField()) { // 普通表单项
					processFormField(fileItem);
				} else { // 上传表单项
					processUploadField(fileItem);
				}

			}

		} catch (FileUploadBase.FileSizeLimitExceededException e) {
			throw new RuntimeException("上传的文件过大不能超过,请重新上传");
		} catch (FileUploadException e) {
			e.printStackTrace();
		}

	}

	// 文件表单项
	private void processUploadField(FileItem fileItem) {
		// 获取文件上传的名字
		String fileName = fileItem.getName();
		// 得到文件输入流
		try {
			InputStream inputStream = fileItem.getInputStream();// 将上传的文件读取到程序中

			// 创建一个目录存放获取到的文件
			// ServletContext.getRealPath() 是从当前servlet 在tomcat 中的存放文件夹开始计算起的
			// 在当前servlet 在tomcat 中的存放文件夹中创建一个upload文件
			File storeDirectory = new File(this.getServletContext().getRealPath("/WEB-INF/upload"));// 让外界访问不到,保证服务器安全,上传的文件放在WEB-INF下
			// 如果文件不存在,则创建文件
			if (!storeDirectory.exists()) {
				storeDirectory.mkdirs();
			}
			// 在当前servlet 在tomcat
			// 中的存放文件夹中创建一个upload文件,的基础上,创建一个完整的位置存放获取到的文件的存放位置
			// 处理上传的文件的文件名fileName(遇到的问题:不同浏览器的使用fileItem.getName()得到的文件名不同,IE的是C:\Users\Administrator\Desktop\2AWA0[$`YCL7%AIZ%SD0$[P.jpg,其他的有的是只有文件名,不加路径)
			if (fileName != null) {
				fileName = FilenameUtils.getName(fileName);
			}
			// 避免文件被覆盖,解决文件同名问题
			fileName = UUID.randomUUID() + "_" + fileName;

			// 避免同一个文件里面文件过多,将目录打散
			/* String childDirectory = makeChildDirectory(storeDirectory); */// 创建日期的子目录
			String childDirectory = makeChildDirectory(storeDirectory, fileName);

			File file = new File(storeDirectory, childDirectory + File.separator + fileName);// 这个位置就是.../upload/日期/获取到的文件名字
			// 将从程序中读取到的数据写入到创建的文件位置file
			/*
			 * FileOutputStream outStream = new FileOutputStream(file); int len
			 * = 0; byte[] b = new byte[1024]; while ((len =
			 * inputStream.read(b)) != -1) { outStream.write(b, 0, len); }
			 * outStream.close();
			 */
			try {
				fileItem.write(file);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			inputStream.close();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 使用UUID的hashCode编码值创建目录
	 * 
	 * @param storeDirectory
	 * @param fileName
	 * @return s
	 */

	private String makeChildDirectory(File storeDirectory, String fileName) {
		int code = fileName.hashCode();// 得到一个32位的整数
		String hexString = Integer.toHexString(code);// 将得到的code转换成16进制的字符串
		String s = hexString.charAt(0) + File.separator + hexString.charAt(1);// 格式:5/6
		// 使用上面得到的字符串创建二级目录
		File file = new File(storeDirectory, s);
		if (!file.exists()) {
			file.mkdirs();
		}
		return s;
	}

	/**
	 * 创建带日期的子目录
	 * 
	 * @param storeDirectory
	 * @return date
	 *//*
		 * private String makeChildDirectory(File storeDirectory) { //格式化日期
		 * SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd"); String date =
		 * sf.format(new Date()); //创建一个新的目录:原来的storeDirectory+日期 File file=new
		 * File(storeDirectory,date); if (!file.exists()) { file.mkdirs(); }
		 * return date; }
		 */

	// 普通表单项
	private void processFormField(FileItem fileItem) {
		// 字段名
		String fieldName = fileItem.getFieldName();
		// 字段值
		String fieldValue;
		try {
			fieldValue = fileItem.getString("UTF-8");
			System.out.println(fieldName + "===" + fieldValue);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

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

		doGet(request, response);
	}

}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值