文件上传和下载

一、文件的上传和下载

  • 文件上传和下载的必要前提:
    a:提拱form表单,method必须为post提交,使用的get的方式是不安全的,而且数据量太小
    b:form表单的enctype必须是multipart/form-data
    c:提拱input type="file"类的上传输入域
  • enctype
    作用:告知服务器请求正文的MIME(相当于文件的类型:如text,jsp)类型。(请求消息头:Context-Type作用是一致的)
    可选值:
    application/x-www-form-urlencoded(默认)
    正文:name=tom&password=123
    服务器获取数据:String name=request.getParameter(“name”);
    multipart/form-data:
    正文
    文件上传和下载_第1张图片
    文件上传和下载_第2张图片
    服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单己经不再是字符内容。而是字节内容,所以失败。方便上传就是请求正文每部分内容。
  • 借助第三方的上传组件实现文件上传
    fileupload概述
    它是由apache的commons组件提拱的上传组件,它最主要的工作就是帮我我们解析request.getInputStream();
    使用方法
    导入commons-fileupload相关的jar包:
    1、commons-fileupload.jar核心包;2、commons-io.jar依赖包
    核心类有:
    1、DiskFileItemFactory(与磁盘打交道)
    2、ServletFileUpload(操作表单项)
    3、FileItem(表单项)
    文件上传和下载_第3张图片
    fileupload的创建使用
    使用fileupload组件的步骤如下:
    1、创建工厂类DiskFileItemFactory对象:
    DiskFileItemFactory factory = new DiskFileItemFactory();
    2、使用工厂创建解析器对象:
    ServletFileUpload fileUpload = new ServletFileUpload(factory);
    3、使用解析器来解析request对象:
    List< FileItem > list = fileUpload.parseRequest(request);
    文件上传和下载_第4张图片
    FileItem对象对应一个表单项(表单字段)。可以是文件字段或者普通字段
    (1)、boolean isFormField();判断当前表单字段是否为普通字段,如果是普通字段返回true,否则是false
    (2)、String getFieldName();获取字段名称,例如:
    < input type=“text” name=“s” /> 返回s
    (3)、String getString();获取字段的内容,如果是文件字段,那么获取的是文本内容,当然上传的文件必须是文本文件
    (4)、String getName();获取文件字段的文件名称;(a.txt)
    (5)、String getContentType();获取获取上传的文件的类型,例如:text/plain
    (6)、int getSize();获取上传文件的大小
    (7)、InputStream getInputStream();获取上传文件对应的输入流
    (8)、void write(File):把上传的文件保存到指定文件中
    文件字段
    文件上传和下载_第5张图片
  • 文件上传时要考虑的几个问题
    a、获取文件名时,根据浏览器的不同,而存在的问题,比如说:a浏览器是a.txt,而b浏览器则是sds/a.txt就会出现问题
    解决:
    文件上传和下载_第6张图片
    争对上面还可以写成这样:
    fileName = fileName.substring(filename.lastIndexOf(File.separator) + 1);File.separator代表 \
    b、保证服务器安全,例如用户上传一个.jsp可执行文件,而在直接在服务器执行,就有很大的安全隐患所以解决办法就是放在一个服务器访问不了地方就可以了
    在这里插入图片描述
    c、解决文件同名而被覆盖的问题:让文件名唯一就可以了
    文件上传和下载_第7张图片
    d、解决同一个目录存储过多的文件
    方案一:按照日期打散
    文件上传和下载_第8张图片
    方案二按目录打散
    文件上传和下载_第9张图片
    d、限制文件的大小:web方式不适合上传大的文件
    单个文件大小:
    ServletFileUpload.setFileSizeMax(字节);
    总文件大小:(多文件上传)
    ServletFileUpload.setSizeMax(字节);
    e、上传字段用户为空的问题
    能过判断文件名是为空就可以了;
    f、临时文件的问题
    DiskFileItemFactory
    作用:产生FileItem对象
    内部有一个缓存,缓存大小默认是10kb,如果上传的文件超过10kb,用磁盘作为缓存,存缓存文件的目录在哪里?默认是系统的临时目录。
    如果自己用IO流实现的文件上传,要在流关闭后,清理临时文件,FileItem.delete();

总的结合内容

/**
 * Servlet implementation class LoginUploadServlet
 */
public class LoginUploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LoginUploadServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//判断是否是multipart/form-data请求
		if(!ServletFileUpload.isMultipartContent(request)) {
			throw new RuntimeException("服务器异常,上传文件出现内部异常");
		}
		//创建一个DiskFileitemFactory工厂类
		DiskFileItemFactory dfif = new DiskFileItemFactory();
		//创建一个ServletFileUpload上传文件核心类
		ServletFileUpload sfu = new ServletFileUpload(dfif);
		//设置编码
		sfu.setHeaderEncoding("UTF-8");
		//设置临时文件存放位置
		dfif.setRepository(new File("//Users//fhvk.game//Desktop//Java学习//temp"));
		//设置文件上传的最大总限
		sfu.setSizeMax(1024*1024*6);  //6m
		try {
			//获取所有表单项
			Map> map = sfu.parseParameterMap(request);
			for (Map.Entry> fileitem : map.entrySet()) {
				for (FileItem list : fileitem.getValue()) {
					//如果是普通的表单项
					if(list.isFormField()) {
						processFormField(list);
					}else {
						//文件表单项
						processUploadField(list);
					}
				}
			}
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//文件表单项
	private void processUploadField(FileItem list) {
		// TODO Auto-generated method stub
		//先获取文件名
		String filename = list.getName();
		//判断如果为空就不创建文件
		if(filename.equals("")) {
			System.out.println("没有文件");
			return;
		}
		//解决可能因为浏览器而导致的问题
		filename = FilenameUtils.getName(filename);
		//解决文件名重复的问题
		filename = UUID.randomUUID() + "_" + filename;
		//获取输入流
		try {
			InputStream is = list.getInputStream();
			//创建一个文件夹存放文件
			File storeDirectory = new File(this.getServletContext().getRealPath("/WEB-INF/upload"));
			//如果不文件夹存在,就创建
			if(!storeDirectory.exists()) {
				storeDirectory.mkdirs();
			}
			//将文件打散
			String newPath = makeChildDiretory(storeDirectory);
			//将文件写到磁盘
			list.write(new File(storeDirectory + File.separator + newPath + File.separator + filename));
			//删除临时文件
			list.delete();
			is.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("----------------UploadField----------------");
		System.out.println(list.getName() + "文件上传成功!");
		System.out.println();
	}
	//通过日期
	private String makeChildDiretory(File storeDirectory) {
		// TODO Auto-generated method stub
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String datePath = sdf.format(new Date().getTime());
		File datefile = new File(storeDirectory, datePath);
		if(!datefile.exists()) {
			datefile.mkdirs();
		}
		return datePath;
	}

	//普通表单项
	private void processFormField(FileItem list) {
		// TODO Auto-generated method stub
		String name = list.getFieldName(); //获取字段名称
		String value = list.getString();//获取字段值
		try {
			value = new String(value.getBytes("iso-8859-1"),"utf-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("----------------FormField----------------");
		System.out.println("name = " + name + " | value = " + value);
		System.out.println();
	}
}

  • 动态添加上传文件按扭
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Insert title here



	
name


文件的下载

package com.lichaowu.web.servlet;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;



public class DownloadServlet extends  HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		resp.setContentType("text/html;charset=UTF-8");
		//获取要下载的文件路径
		String path = "销售榜单.csv";
		//解决编码问题
		if(req.getHeader("user-agent").toLowerCase().contains("mise")) {
			path = URLEncoder.encode(path, "UTF-8");
		}else {
			System.out.println("sds");
			path = new String(path.getBytes("UTF-8"),"iso-8859-1");
		}
		//告诉浏览器要下载文件
		resp.setHeader("content-disposition", "attachment;filename=" + path);
		//设置文件下载类型
		resp.setContentType(this.getServletContext().getMimeType(path));
		
		
		//得到输出流
		PrintWriter writer = resp.getWriter();
		writer.write("电视机,20\n");
		writer.write("洗衣机,10\n");
		writer.write("冰箱,22\n");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doPost(req, resp);
	}
}

运用在图书管理系统中

  • 添加书籍Servlet
public class BookAddServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public BookAddServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
//		//获取表单数据
//		Book book = new Book();
//		 try {
//			BeanUtils.populate(book, request.getParameterMap());
//			book.setId(UUIDutil.getId());
//			//处理业务逻辑
//			BookService bs = new BookServiceImpl();
//			bs.addBook(book);
//			//分发转向
//			request.getRequestDispatcher("/BookListServlet").forward(request, response);
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} 
		//获取表单数据
		//创建DiskFileItemFactory工厂类
		DiskFileItemFactory dfif = new DiskFileItemFactory();
		//创建一个SerlvetFileUpload核心类
		ServletFileUpload sfu = new ServletFileUpload(dfif);
		sfu.setHeaderEncoding("UTF-8");
		//创建一个map存储普通表单项数据
		Map map  = new HashMap();
		try {
			//解析request,返回表单项集合
			Map> parseParameterMap = sfu.parseParameterMap(request);
			//遍历
			for (Map.Entry> element : parseParameterMap.entrySet()) {
				for (FileItem fileitem : element.getValue()) {
					if(fileitem.isFormField()) {
						//如果是普通表单项
						String name = fileitem.getFieldName();
						String value = fileitem.getString("UTF-8");
						System.out.println(value);
						//存到map集合中
						map.put(name, new String[]{value});
					}else {
						//如果是文件表单项
						//先获取文件名
						String filename = fileitem.getName();
						System.out.println("filename1 = " + filename);
						//解决文件名的问题
						if(filename != null) {
							filename = FilenameUtils.getName(filename);
						}
						//在指定位置创建一个文件夹存放上传的文件
						File newfile = new File(this.getServletContext().getRealPath("/upload"));
						//创建
						if(!newfile.exists()) {
							//如果不存在就new一个出来
							newfile.mkdirs();
						}
						//文件打散
						String newpath = makeChildDirectory(newfile, filename);
						filename =  newpath + File.separator + filename;
						System.out.println("打散后:" + filename);
						//获取文件输入流
						InputStream fis = fileitem.getInputStream();
						//将文件写到指定文件夹
						fileitem.write(new File(newfile, filename));
						//删除临时文件
						fileitem.delete();
						//将文件路径存储到map集合中
						map.put(fileitem.getFieldName(), new String[]{filename});
					}
				}
			}
			Book book = new Book();
			BeanUtils.populate(book, map);
			book.setId(UUIDutil.getId());
			System.out.println(book);
			//处理业务逻辑
			BookService bs = new BookServiceImpl();
			bs.addBook(book);
			//分发转向
			request.getRequestDispatcher("/BookListServlet").forward(request, response);
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	//目录打散
	private String makeChildDirectory(File newfile, String filename) {
		// TODO Auto-generated method stub
		int hashcode = filename.hashCode();  //获取文件名hashcode值
		String newpath = Integer.toHexString(hashcode);  //将hashcode值转换为十六进制的字符串
		//取两个字符作为目录
		String file = newpath.charAt(0) + File.separator + newpath.charAt(1);
		File newFile = new File(newfile, file);
		if(!newFile.exists()) {
			newFile.mkdirs();
		}
		return file;
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

你可能感兴趣的:(Java,Java文件上传和下传)