Java文件的上传和下载
一、文件上传
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文件的上传和下载相关推荐
- 初学Java Web(7)——文件的上传和下载
文件上传 文件上传前的准备 在表单中必须有一个上传的控件 <input type="file" name="testImg"/> 因为 GET 方式 ...
- java实现ftp文件的上传与下载
最近在做ftp文件的上传与下载,基于此,整理了一下资料.本来想采用java自带的方法,可是看了一下jdk1.6与1.7的实现方法有点区别,于是采用了Apache下的框架实现的... 1.首先引用3个包 ...
- FastDFS:Java客户都实现文件的上传、下载、修改、删除
FastDFS:Java客户都实现文件的上传.下载.修改.删除 <project xmlns="http://maven.apache.org/POM/4.0.0" xmln ...
- nginx java文件上传_Nginx实现文件的上传和下载
文件的上传只要保证特殊的地址先到达Nginx,然后通过Nginx指定至指定的服务器即可,目前配置是本机.文件的下载的做法就是把本机的当前目录下面的文件给返回回去. server { listen ; ...
- java struts2下载文件_Struts2下多文件的上传与下载
Struts2下多文件的上传与下载 目录 多文件 上传 下载 随意文件java Struts2单例 配置 动态读取 李顺利 在网络上,对于Java处理文件上传和下载的技术比较多,而Struts作为一款 ...
- java图片上传下载_java实现文件的上传和下载
1. servlet 如何实现文件的上传和下载? 1.1上传文件 参考自:http://blog.csdn.net/hzc543806053/article/details/7524491 通过前台选 ...
- Hadoop环境下用java代码实现hdfs远程文件的上传和下载
Hadoop环境下用java代码实现hdfs远程文件的上传和下载 文章目录 Hadoop环境下用java代码实现hdfs远程文件的上传和下载 一.新建maven工程 二.文件的上传 三.文件的下载 四 ...
- 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 ...
- SpringMVC实现文件的上传和下载
SpringMVC实现文件的上传和下载http://www.bieryun.com/1120.html 前些天一位江苏经贸的学弟跟我留言问了我这样一个问题:"用什么技术来实现一般网页上文件的 ...
- SpringMVC实现文件的上传与下载
文件的上传与下载可以说是工作中经常使用的功能,现在整理一下,希望能够给大家一个参考.这里以 Maven 的形式来创建项目,相关的配置文件会把主要的内容列出来,其他头文件信息不再一一全部的列出.最后会把 ...
最新文章
- CV04-UNet笔记
- jQuery之父强烈推荐之jQuery实战
- subline Text3
- gpu云服务器运行游戏_GPU云服务器可以挂载大型游戏吗?
- 【机器学习基础】终于把XGBoost总结写出来了!
- SCCM2007 R2的部署前准备,SCCM系列之一
- 从SAP客户主数据里直接创建商机(Opportunity) 1
- Rect 的相关操作
- MVC控制器取参数值
- 海康 Isecure VMS 客户端二次开发简单记录
- 无线WIFI I/O控制器技术分享
- 创智播客微服务_传智播客黑马程序员首次对外发布JavaEE中级程序员学习路线图...
- win7 美化Linux,让XP的主题背景拥有Win7一样的华丽 让Linux系统和Win8一模一样!超华丽Linux仿Win...
- 【论文阅读】【因果关系】
- 打印机共享无法访问该计算机,共享打印机拒绝访问怎么办详细解决方案
- 最新版本的mmdetection2.0 (v2.0.0版本)环境搭建、训练自己的数据集、测试以及常见错误集合
- 图像分割之(四)OpenCV的GrabCut函数使用和源码解读
- 传感器响应时间与滤波器截止频率的关系
- 【BZOJ1135】【POI2009】Lyz
- android getpixel函数,关于Graphics.Blit函数在android上的巨坑
热门文章
- SFP光纤收发器搭配光模块的交换机连接方案解决方案
- wireshark抓取未加密聊天数据
- IPV6个人使用,实测电脑ping通联通手机
- 字节和兆字节的换算_兆字节(MB)中有多少个字节?
- 第二人生的源码分析(七十六)判断程序运行多个实例
- win7系统没有telnet服务器,win7没有telnet命令 win7无法使用telnet
- status(c语言)
- Java银联在线网关支付测试总结
- Jupyter/IPython笔记本集合 !(附大量资源链接)-上篇
- android studio 使用xml:app命名空间代码不提示问题