20160420javaweb之文件上传和下载

一、文件上传
1.提供表单允许用户通过表单选择文件进行上传
表单必须是POST提交
文件输入框必须有name属性,只有有name属性的输入项浏览器才会进行提交
需要设置enctype属性值为multipart/form-data

POST /Day15/upload.jsp HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://localhost/Day15/upload.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Content-Type: multipart/form-data; boundary=---------------------------7de1e62806e0
Accept-Encoding: gzip, deflate
Host: localhost
Content-Length: 394
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=818C14110CA7BFD1FC90610866A220E8

-----------------------------7de1e62806e0
Content-Disposition: form-data; name="description1"

xxxx
-----------------------------7de1e62806e0
Content-Disposition: form-data; name="description2"

zzzz
-----------------------------7de1e62806e0
Content-Disposition: form-data; name="file1"; filename="ip.txt"
Content-Type: text/plain

192
-----------------------------7de1e62806e0--

2.在Servlet中将上传的文件保存在服务器的硬盘中
DiskFileItemFactory
public DiskFileItemFactory(int sizeThreshold, java.io.File repository)

public DiskFileItemFactory()
public void setSizeThreshold(int sizeThreshold) --用来设定内存缓冲区的大小,默认是10k
public void setRepository(java.io.File repository) --设定临时文件夹的大小

ServletFileUpload
boolean isMultipartContent(HttpServletRequest request) 判断上传表单是否为multipart/form-data类型
List parseRequest(HttpServletRequest request) 解析request对象,并把表单中的每一个输入项包装成一个fileItem 对象,并返回一个保存了所有FileItem的list集合。
setFileSizeMax(long fileSizeMax) 设置单个上传文件的最大值
setSizeMax(long sizeMax) 设置上传文件总量的最大值
setHeaderEncoding(java.lang.String encoding) 设置编码格式,解决上传文件名乱码问题
setProgressListener(ProgressListener pListener) 实时监听文件上传状态

FileItem
boolean isFormField() 判断FileItem是一个文件上传对象还是普通表单对象
示例代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>文件上传</h1><hr>
<form action="${pageContext.request.contextPath }/UploadFileServlet" method="post" enctype="multipart/form-data">
     描述信息1:<input type="text" name="description1"/>
       描述信息2:<input type="text" name="description2"/>
       <input type="file" name="file1"/>
       <input type="submit" value="上传"/>
</form>
</body>
</html>
package com.dzq.web;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

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

import com.dzq.utils.IOUtils;

@WebServlet("/UploadFileServlet")
public class UploadFileServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*InputStream is=request.getInputStream();
        byte[] bs=new byte[1024];
        int i=0;
        while((i=is.read(bs))!=-1){
            System.out.write(bs,0,i);
        }
        is.close();*/

        try {
            //1.创建工厂
            DiskFileItemFactory factory =new DiskFileItemFactory();
            //2.生产文件上传核心类
            ServletFileUpload fileupload=new ServletFileUpload(factory);
            //3.利用文件上传核心类解析request
            List<FileItem> list=fileupload.parseRequest(request);
            //4.遍历所有的fileitem
            for(FileItem item:list){
                if(item.isFormField()){
                    //当前是普通字段项
                    String name=item.getFieldName();
                    String value=item.getString();
                    System.out.println(name+":"+value);
                }else{
                    //当前是一个文件上传项
                    String filename=item.getName();
                    InputStream in=item.getInputStream();
                    OutputStream out=new FileOutputStream(this.getServletContext().getRealPath("/upload"+filename));
                    IOUtils.In2Out(in, out);
                    IOUtils.close(in, out);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

}
package com.dzq.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class IOUtils {
   private IOUtils(){

   }

   public static void In2Out(InputStream in,OutputStream out) throws IOException{
       byte[] bs=new byte[1024];
       int i=0;
       while ((i=in.read(bs))!=-1) {
        out.write(bs,0,i);
    }
   }

   public static void close(InputStream in,OutputStream out){
       if(in!=null){
           try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            in=null;
        }
       }

       if(out!=null){
           try {
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            out=null;
        }
       }
   }
}

如果是一个普通字段项可以调用:
String getFieldName() 获得普通表单对象的name属性
String getString(String encoding) 获得普通表单对象的value属性,可以用encoding进行编码设置

如果是一个文件上传项:
String getName() 获得上传文件的文件名(有些浏览器会携带客户端路径)
InputStream getInputStream() 获得上传文件的输入流
delete() 在关闭FileItem输入流后,删除临时文件

文件存放应该注意的问题:
1.upload文件夹和temp文件夹都要放在web-inf目录下保护起来,防止上传入侵和访问其他用户上传资源的问题
2.文件名要拼接uuid保证唯一
3.文件要分目录存储保证同一目录下不要有过多的文件,分目录的算法有很多,介绍了一种根据hash值分目录算法

文件上传的一些细节:

package com.itheima.web;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
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.ProgressListener;
import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.itheima.util.IOUtils;

public class UploadServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        try{
            //1.创建工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(100*1024);
            factory.setRepository(new File(this.getServletContext().getRealPath("WEB-INF/temp")));
            //2.生产文件上传核心类
            ServletFileUpload fileUpload = new ServletFileUpload(factory);

            //--检查是否是正确的文件上传表单
            if(!fileUpload.isMultipartContent(request)){
                throw new RuntimeException("请用正确的表单进行上传!");
            }
            //--设置文件上传的大小限制
//            fileUpload.setFileSizeMax(1024*1024*100);//单个文件不大于10M
//            fileUpload.setSizeMax(1024*1024*100);//总大小不大于100M

            //--设置编码集,解决上传文件名的乱码问题
            fileUpload.setHeaderEncoding("utf-8");

            //--设置文件上传监听
            fileUpload.setProgressListener(new ProgressListener(){
                Long beginTime = System.currentTimeMillis();
                public void update(long bytesRead, long contentLength, int items) {
                    BigDecimal br = new BigDecimal(bytesRead).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
                    BigDecimal cl = new BigDecimal(contentLength).divide(new BigDecimal(1024),2,BigDecimal.ROUND_HALF_UP);
                    System.out.print("当前读取的是第"+items+"个上传项,总大小"+cl+"KB,已经读取"+br+"KB");
                    //剩余字节数
                    BigDecimal ll = cl.subtract(br);
                    System.out.print("剩余"+ll+"KB");
                    //上传百分比
                    BigDecimal per = br.multiply(new BigDecimal(100)).divide(cl,2,BigDecimal.ROUND_HALF_UP);
                    System.out.print("已经完成"+per+"%");
                    //上传用时
                    Long nowTime = System.currentTimeMillis();
                    Long useTime = (nowTime - beginTime)/1000;
                    System.out.print("已经用时"+useTime+"秒");
                    //上传速度
                    BigDecimal speed = new BigDecimal(0);
                    if(useTime!=0){
                        speed = br.divide(new BigDecimal(useTime),2,BigDecimal.ROUND_HALF_UP);
                    }
                    System.out.print("上传速度为"+speed+"KB/S");
                    //大致剩余时间
                    BigDecimal ltime = new BigDecimal(0);
                    if(!speed.equals(new BigDecimal(0))){
                        ltime = ll.divide(speed,0,BigDecimal.ROUND_HALF_UP);
                    }
                    System.out.print("大致剩余时间为"+ltime+"秒");

                    System.out.println();
                }

            });

            //3.利用文件上传核心类解析request
            List<FileItem> list = fileUpload.parseRequest(request);
            //4.遍历所有的FileItem
            for(FileItem item : list){
                if(item.isFormField()){
                    //当前是一个普通的字段项
                    String name = item.getFieldName();
                    String value = item.getString("utf-8");
                    System.out.println(name+":"+value);
                }else{
                    //当前是一个文件上传项
                    String filename = item.getName();
                    String uuidName = UUID.randomUUID().toString()+"_"+filename;

                    int hash = uuidName.hashCode();
                    String hashStr = Integer.toHexString(hash);
                    char [] hss = hashStr.toCharArray();
                    String path = this.getServletContext().getRealPath("WEB-INF/upload");
                    for(char c : hss){
                        path+="/"+c;
                    }
                    new File(path).mkdirs();

                    InputStream in = item.getInputStream();
                    OutputStream out = new FileOutputStream(new File(path,uuidName));

                    IOUtils.In2Out(in, out);
                    IOUtils.close(in, out);

                    //--删除临时文件
                    item.delete();
                }
            }
        }catch (FileSizeLimitExceededException e) {
            response.getWriter().write("单个文件不超过10M,总大小不超过100M!");
            return;
        }catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

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

}

二、文件下载
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"utf-8"));
response.setContentType(this.getServletContext().getMimeType(filename));//MIME类型

下载示例源码:

package com.dzq.web;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.dzq.utils.IOUtils;

@WebServlet("/DownServlet")
public class DownServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取要下载的资源的名称

         String filename = request.getParameter("file");
        response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"utf-8"));
        response.setContentType(this.getServletContext().getMimeType(filename));//MIME类型

        InputStream in = new FileInputStream(this.getServletContext().getRealPath("/"+filename));
        OutputStream out = response.getOutputStream();
        IOUtils.In2Out(in, out);
        IOUtils.close(in, null);
        //2.读取资源

    }

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

}
时间: 2025-01-01 11:54:16

20160420javaweb之文件上传和下载的相关文章

JavaWeb学习总结(五十)——文件上传和下载

在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件.这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,stru

深入分析JavaWeb Item40 -- 文件上传和下载

在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件.这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,stru

文件上传与下载!

1.上传: 1.上传数据的类型:字符,字节 1.文本类型(字符):通过url网址的?:通过表单元素:AJAX. 2.文件类型(字节):通过表单元素(file). 2.上传文件的方式: 1.form表单实现文件上传:常用方式(上传文件用post,不用get,因为get方式对于上传量有限) 通过鼠标单击,在File标签中选择的文件,才能上传. 2.通过AJAX实现文件上传:禁用方式   AJAX的数据传递通过javascript脚本取值.如果传递文件,那么也需要通过javascript脚本获取文件内

springmvc和servlet下的文件上传和下载(存文件目录和存数据库Blob两种方式)

项目中涉及了文件的上传和下载,以前在struts2下做过,今天又用springmvc做了一遍,发现springmvc封装的特别好,基本不用几行代码就完成了,下面把代码贴出来: FileUpAndDown.jsp <%@ page language="java" contentType="text/html; charset=UTF-8"%> <html> <head> <title>using commons Uplo

struts2中的文件上传和下载

天下大事,必做于细.天下难事,必作于易. 曾经见过某些人,基础的知识还不扎实就去学习更难的事,这样必然在学习新的知识会很迷惑结果 再回来重新学习一下没有搞懂的知识,这必然会导致学习效率的下降!我写的这篇上传和下载都很基础. 十分适合初学者! jsp:页面 <!--在进行文件上传时,表单提交方式一定要是post的方式,因为文件上传时二进制文件可能会很大,还有就是enctype属性,这个属性一定要写成multipart/form-data, 不然就会以二进制文本上传到服务器端--> <for

JavaWeb文件上传和下载

在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请 求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件.这个common- fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,st

Linux 指令篇:文件上传和下载 lrzsz

[ "lrzsz"一般用于SecureCRT ssh中使用 ] 简介:rz,sz是早期Linux/Unix同Windows进行ZModem文件传输的命令行工具.rz ,sz 是非常古老的zmodem协议使用的上传下载命令,早就被抛弃了的东西,目前的发行版基本都不再预装. 优点:比ftp命令方便,而且服务器不用打开FTP服务. 命令sz:将选定的文件发送(send)到本地机器 命令rz:运行该命令会弹出一个文件选择窗口,从本地选择文件上传到Linux服务器. lrzsz安装方法: [[e

FileUpload系列:(3)文件上传和下载示例

示例由1个Servlet和3个JSP组成. 1.FileServlet package com.rk.web.servlet; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.util.Has

JavaWeb学习总结,文件上传和下载

在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件.这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,stru