一、文件上传

1、文件上传的原理分析

把文件从客户端传递到服务器的过程就是文件上传。

1.1文件上传的必要前提:

a、提供form表单,method必须是post

b、form表单的enctype必须是multipart/form-data

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

1.2enctype属性

作用:告知服务器请求正文的MIME类型。(请求消息头:Content-Type作用是一致的)

可选值:

l  application/x-www-form-urlencoded(默认):

正文:name=admin&password=123

服务器获取数据:String name =request.getParameter("name");

l  multipart/form-data:

正文:

服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。

文件上传:解析请求正文的每部分的内容。

2、借助第三方的上传组件实现文件上传

2.1 fileupload概述

fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。

导入commons-fileupload相关jar包

l  commons-fileupload.jar,核心包;

地址:http://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi

l  commons-io.jar,依赖包。

地址:http://commons.apache.org/proper/commons-io/download_io.cgi

2.2 fileupload的核心类有:

DiskFileItemFactory、ServletFileUpload、FileItem。

a、解析原理

2.2 fileupload简单应用

使用fileupload组件的步骤如下:

1.      创建工厂类DiskFileItemFactory对象:

DiskFileItemFactory factory = new DiskFileItemFactory()

2.      使用工厂创建解析器对象:

ServletFileUpload fileUpload = new ServletFileUpload(factory)

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

List<FileItem> list = fileUpload.parseRequest(request)

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

l  boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;

l  String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username;

l  String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;

l  String getName():获取文件字段的文件名称;(a.txt)

l  String getContentType():获取上传的文件的MIME类型,例如:text/plain。

l  int getSize():获取上传文件的大小;

l  InputStream getInputStream():获取上传文件对应的输入流;

l  void write(File):把上传的文件保存到指定文件中。

l  delete();删除临时文件

import java.io.File;
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 UploadServlet2 extends HttpServlet {/*** */private static final long serialVersionUID = 1L;@SuppressWarnings("unchecked")public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 判断表单的提交类型是否是enctype="multipart/form-data"boolean isMultipart = ServletFileUpload.isMultipartContent(request);if (isMultipart) {try {// 创建一个解析器工厂类DiskFileItemFactory factory = new DiskFileItemFactory();//factory.setRepository(new File("f:/"));//把临时文件保存到f盘下// 通过工厂创建解析器ServletFileUpload upload = new ServletFileUpload(factory);upload.setHeaderEncoding("UTf-8");// 解决上传文件名乱码问题// 限制单个文件上传的大小upload.setFileSizeMax(1024 * 1024 * 3);// 文件限制为3M// 限制文件上传的总大小upload.setSizeMax(1024*1024*6);//文件总大小不能超过6M// 解析request对象List<FileItem> fileItems = upload.parseRequest(request);for (FileItem fileItem : fileItems) {if (fileItem.isFormField()) {// 判断是否是普通表单项(true:是普通表单项)processFormField(fileItem);} else {processUploadFile(fileItem);}}} catch (FileUploadBase.FileSizeLimitExceededException e) {System.out.println("上传文件过大,不能超过3M");} catch (FileUploadBase.SizeLimitExceededException e) {System.out.println("上传文件过大,总大小不能超过6M");} catch (FileUploadException e) {e.printStackTrace();}}}// 解析上传文件表单项private void processUploadFile(FileItem fileItem) {try {// 得到name的值 name="photo"String name = fileItem.getFieldName();// 得到文件名String filename = fileItem.getName(); // F:\图片素材\有范儿\25.jpg 或 25.jpg// 文件内容InputStream in = fileItem.getInputStream();System.out.println(name + "\t" + filename);// 创建一个目录 File即代表文件又代表目录File storeDirectory = new File(this.getServletContext().getRealPath("/upload"));if (!storeDirectory.exists()) {storeDirectory.mkdirs();// 创建目录}// 解决文件名路径问题// filename = filename.substring(filename.lastIndexOf("/")+1);filename = FilenameUtils.getName(filename);//得到文件的扩展名String extension = FilenameUtils.getExtension(filename);//只能上传jpg和txt文件/*if(!("jpg".equals(extension)||"txt".equals(extension))){return;}*/// 解决文件名冲突的问题filename = UUID.randomUUID() + "_" + filename;// 创建子目录(目录打散)String childDirectory = makeChildDirectory1(storeDirectory,filename);// 创建文件File file = new File(storeDirectory, childDirectory + "/"+ filename); // F:\\apache-tomcat-7.0.52\\webapps\\day20_00_upload\\upload\\F:\\图片素材\\有范儿\\25.jpg// 创建一个文件输出流fileItem.write(file);/* OutputStream out = new FileOutputStream(file); int len = 0;byte[] b = new byte[1024]; while((len=in.read(b))!=-1){out.write(b, 0, len); }out.close(); in.close();*/fileItem.delete();//删除临时文件} catch (Exception e) {e.printStackTrace();}}// 创建子目录2private String makeChildDirectory1(File storeDirectory, String filename) {int hashCode = filename.hashCode();// 得到一个32位的整数String hexString = Integer.toHexString(hashCode);// 把整数转换成16进制的字符串// 65fsad32fhfString child = hexString.substring(0, 1) + "/"+ hexString.substring(1, 2); // 6/5File childDirectory = new File(storeDirectory + "/" + child);if (!childDirectory.exists()) {childDirectory.mkdirs();}return child;}// 创建子目录(以日期为单位)private String makeChildDirectory(File storeDirectory) {Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");String fdate = sdf.format(date); // 2016-05-07// 创建目录File childDirectory = new File(storeDirectory + "/" + fdate);if (!childDirectory.exists()) {childDirectory.mkdirs();}return fdate;}// 解析普通表单项private void processFormField(FileItem fileItem) {try {String name = fileItem.getFieldName();// 得到name="name"String value = fileItem.getString("UTF-8");// 得到valueSystem.out.println(name + "=" + value);} catch (UnsupportedEncodingException e) {e.printStackTrace();}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}

二、文件的下载

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class DownloadServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=GBK");String filename = "销售榜单.csv";//解决文件名不安全的问题filename = URLEncoder.encode(filename, "UTF-8");//告知客户端浏览器下载文件response.setHeader("content-disposition", "attachment;filename="+filename);//告知浏览器下载文件的格式//例:images/jpeg 作用:this.getServletContext().getMimeType(filename)得到文件类型         response.setHeader("content-type", this.getServletContext().getMimeType(filename)); PrintWriter out = response.getWriter();out.write("id,name,price\n");out.write("1,冰箱,200\n");out.write("2,电话机,300\n");out.write("3,复读机,200\n");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}
}

三、Notice

a、文件名处理的问题   得到简单的没有路径文件名31.jpg

// 解决文件名路径问题  filename = filename.substring(filename.lastIndexOf("/")+1);
filename = FilenameUtils.getName(filename);

b、避免文件被覆盖,让文件名唯一即可

// 解决文件名冲突的问题
filename = UUID.randomUUID() + "_" + filename;

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

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

// 创建子目录(以日期为单位)private String makeChildDirectory(File storeDirectory) {Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");String fdate = sdf.format(date); // 2016-05-07// 创建目录File childDirectory = new File(storeDirectory + "/" + fdate);if (!childDirectory.exists()) {childDirectory.mkdirs();}return fdate;}

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

// 创建子目录2private String makeChildDirectory1(File storeDirectory, String filename) {int hashCode = filename.hashCode();// 得到一个32位的整数String hexString = Integer.toHexString(hashCode);// 把整数转换成16进制的字符串 // 65fsad32fhfString child = hexString.substring(0, 1) + "/"+ hexString.substring(1, 2); // 6/5File childDirectory = new File(storeDirectory + "/" + child);if (!childDirectory.exists()) {childDirectory.mkdirs();}return child;}

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

单个文件大小:

ServletFileUpload.setFileSizeMax(字节)

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

ServletFileUpload.setSizeMax(字节)

// 创建一个解析器工厂类
DiskFileItemFactory factory = new DiskFileItemFactory();
//factory.setRepository(new File("f:/"));//把临时文件保存到f盘下
// 通过工厂创建解析器
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTf-8");// 解决上传文件名乱码问题
// 限制单个文件上传的大小
upload.setFileSizeMax(1024 * 1024 * 3);// 文件限制为3M
// 限制文件上传的总大小
upload.setSizeMax(1024*1024*6);//文件总大小不能超过6M
// 解析request对象
List<FileItem> fileItems = upload.parseRequest(request);

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

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

f、临时文件的问题

DiskFileItemFactory:

作用:产生FileItem对象

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

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

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

FileItem.delete();

Java文件的上传和下载相关推荐

  1. 初学Java Web(7)——文件的上传和下载

    文件上传 文件上传前的准备 在表单中必须有一个上传的控件 <input type="file" name="testImg"/> 因为 GET 方式 ...

  2. java实现ftp文件的上传与下载

    最近在做ftp文件的上传与下载,基于此,整理了一下资料.本来想采用java自带的方法,可是看了一下jdk1.6与1.7的实现方法有点区别,于是采用了Apache下的框架实现的... 1.首先引用3个包 ...

  3. FastDFS:Java客户都实现文件的上传、下载、修改、删除

    FastDFS:Java客户都实现文件的上传.下载.修改.删除 <project xmlns="http://maven.apache.org/POM/4.0.0" xmln ...

  4. nginx java文件上传_Nginx实现文件的上传和下载

    文件的上传只要保证特殊的地址先到达Nginx,然后通过Nginx指定至指定的服务器即可,目前配置是本机.文件的下载的做法就是把本机的当前目录下面的文件给返回回去. server { listen ; ...

  5. java struts2下载文件_Struts2下多文件的上传与下载

    Struts2下多文件的上传与下载 目录 多文件 上传 下载 随意文件java Struts2单例 配置 动态读取 李顺利 在网络上,对于Java处理文件上传和下载的技术比较多,而Struts作为一款 ...

  6. java图片上传下载_java实现文件的上传和下载

    1. servlet 如何实现文件的上传和下载? 1.1上传文件 参考自:http://blog.csdn.net/hzc543806053/article/details/7524491 通过前台选 ...

  7. Hadoop环境下用java代码实现hdfs远程文件的上传和下载

    Hadoop环境下用java代码实现hdfs远程文件的上传和下载 文章目录 Hadoop环境下用java代码实现hdfs远程文件的上传和下载 一.新建maven工程 二.文件的上传 三.文件的下载 四 ...

  8. Java ftp实现文件的上传和下载ftp,sftp sun.net.ftp.FtpProtocolException:Welcome message: SSH-2.0-OpenSSH_5.1

    Java ftp实现文件的上传和下载 ftp,sftp 运行后发现很长时间没有反应,很久以后抛出如下异常:sun.net.ftp.FtpProtocolException:Welcome messag ...

  9. SpringMVC实现文件的上传和下载

    SpringMVC实现文件的上传和下载http://www.bieryun.com/1120.html 前些天一位江苏经贸的学弟跟我留言问了我这样一个问题:"用什么技术来实现一般网页上文件的 ...

  10. SpringMVC实现文件的上传与下载

    文件的上传与下载可以说是工作中经常使用的功能,现在整理一下,希望能够给大家一个参考.这里以 Maven 的形式来创建项目,相关的配置文件会把主要的内容列出来,其他头文件信息不再一一全部的列出.最后会把 ...

最新文章

  1. CV04-UNet笔记
  2. jQuery之父强烈推荐之jQuery实战
  3. subline Text3
  4. gpu云服务器运行游戏_GPU云服务器可以挂载大型游戏吗?
  5. 【机器学习基础】终于把XGBoost总结写出来了!
  6. SCCM2007 R2的部署前准备,SCCM系列之一
  7. 从SAP客户主数据里直接创建商机(Opportunity) 1
  8. Rect 的相关操作
  9. MVC控制器取参数值
  10. 海康 Isecure VMS 客户端二次开发简单记录
  11. 无线WIFI I/O控制器技术分享
  12. 创智播客微服务_传智播客黑马程序员首次对外发布JavaEE中级程序员学习路线图...
  13. win7 美化Linux,让XP的主题背景拥有Win7一样的华丽 让Linux系统和Win8一模一样!超华丽Linux仿Win...
  14. 【论文阅读】【因果关系】
  15. 打印机共享无法访问该计算机,共享打印机拒绝访问怎么办详细解决方案
  16. 最新版本的mmdetection2.0 (v2.0.0版本)环境搭建、训练自己的数据集、测试以及常见错误集合
  17. 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
  18. 传感器响应时间与滤波器截止频率的关系
  19. 【BZOJ1135】【POI2009】Lyz
  20. android getpixel函数,关于Graphics.Blit函数在android上的巨坑

热门文章

  1. SFP光纤收发器搭配光模块的交换机连接方案解决方案
  2. wireshark抓取未加密聊天数据
  3. IPV6个人使用,实测电脑ping通联通手机
  4. 字节和兆字节的换算_兆字节(MB)中有多少个字节?
  5. 第二人生的源码分析(七十六)判断程序运行多个实例
  6. win7系统没有telnet服务器,win7没有telnet命令 win7无法使用telnet
  7. status(c语言)
  8. Java银联在线网关支付测试总结
  9. Jupyter/IPython笔记本集合 !(附大量资源链接)-上篇
  10. android studio 使用xml:app命名空间代码不提示问题