Java web开发——文件的上传和下载 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 网站建设 >

Java web开发——文件的上传和下载

发表时间:2018-7-28

发布人:葵宇科技

浏览次数:31

打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

微信

一、文件上传

1、概述

实现web开发中的文件上传功能,需完成如下二步操作:

  • 在web页面中添加上传输入项
  • 在servlet中读取上传文件的数据,并保存到本地硬盘中。

2、在web页面中

在web页面中通过<input type=“file”>标签添加上传输入项,设置文件上传输入项时须注意:

1、必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据。

2、必须把form的enctype属值设为multipart/form-data.设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。

    <form action="${pageContext.request.contextPath }/servlet/UploadServlet3" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="username"><br/>
        上传文件1:<input type="file" name="file1"><br/>
        上传文件2:<input type="file" name="file2"><br/>
        
        <input type="submit" value="提交">
    </form>

注意:如果要动态添加上传输入项可以:

<html>
  <head>
    <title>My JSP 'upload2.jsp' starting page</title>
    
    <script type="text/javascript">
        function addinput(){
            var div = document.getElementById("file");
            
            var input = document.createElement("input");
            input.type="file";
            input.name="filename";
            
            var del = document.createElement("input");
            del.type="button";
            del.value="删除";
            del.onclick = function d(){
                this.parentNode.parentNode.removeChild(this.parentNode);
            }
            
            
            var innerdiv = document.createElement("div");
            
            
            innerdiv.appendChild(input);
            innerdiv.appendChild(del);
            
            div.appendChild(innerdiv);
        }
    </script>
    
  </head>
  
  <body>
    
    
    <form action="" enctype="mutlipart/form-data"></form>
    <table>
        <tr>
            <td>上传用户:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>        
            <td>上传文件:</td>
            <td>
                <input type="button" value="添加上传文件" class="has" src="https://img-blog.csdn.net/20180728200740972?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIyMTcyMTMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" />

3、在Servlet中

1.基本介绍

在Servlet中通过开源组件( Commons-fileupload )读取文件上传数据,并保存到本地硬盘中。使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:

Commons-fileupload和commons-io

注意:如果表单的提交类型为multipart/form-data的话,在servlet方就不能采用传统方式获取表单数据

String username = request.getParameter("username");
System.out.println(username);

2.相关方法

1.DiskFileItemFactory

DiskFileItemFactory 是创建 FileItem 对象的工厂,这个工厂类常用方法:

方法介绍public void setSizeThreshold(int sizeThreshold) 设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。public void setRepository(java.io.File repository) 指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").public DiskFileItemFactory(int sizeThreshold, java.io.File repository) 构造函数

2.ServletFileUpload

负责处理上传的文件数据,并将表单中每个输入项封装成一个 FileItem 对象中。常用方法有:

方法介绍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) 上传监听器,可以知道文件上传进度

3.servlet实现

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
?
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
?
public class UploadServlet2 extends HttpServlet {
?
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try{

            //1.得到解析器工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //设置缓存文件路径(临时文件)
            factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp"))); 

            //2.得到解析器
            ServletFileUpload upload = new ServletFileUpload(factory);      
?
            upload.setHeaderEncoding("UTF-8");  //解决上传文件名的中文乱码
            //3.判断上传表单的类型
            if(!upload.isMultipartContent(request)){
                //上传表单为普通表单,则按照传统方式获取数据即可
                return;
            }

            //为上传表单,则调用解析器解析上传数据
            List<FileItem> list = upload.parseRequest(request);  //FileItem

            //遍历list,得到用于封装第一个上传输入项数据fileItem对象
            for(FileItem item : list){

                if(item.isFormField()){
                    //得到的是普通输入项
                    String name = item.getFieldName();  //得到输入项的名称
                    String value = item.getString("UTF-8");//或者String value = item.getString();加下
                    //value = new String(value.getBytes("iso8859-1"),"UTF-8");
                    System.out.println(name + "=" + value);
                }else{
                    //得到上传输入项
                    String filename = item.getName();  //得到上传文件名  C:\Documents and Settings\ThinkPad\桌面\1.txt(有些浏览器)||1.txt
                    if(filename==null || filename.trim().equals("")){//如果上传输入框为空,跳出
                        continue;
                    }
                    filename = filename.substring(filename.lastIndexOf("\\")+1);
                    InputStream in = item.getInputStream();   //得到上传数据
                    int len = 0;
                    byte buffer[]= new byte[1024];


                    String savepath = this.getServletContext().getRealPath("/upload");
                    FileOutputStream out = new FileOutputStream(savepath + "\\" + filename);  //向upload目录中写入文件
                    while((len=in.read(buffer))>0){
                        out.write(buffer, 0, len);
                    }

                    in.close();
                    out.close();
                    item.delete();//删除临时文件
                }
            }

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

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

注意:

1.上传的文件一般禁止别人访问,故可以放在WEB-INF目录下

//用于保存上传文件的目录应该禁止外界直接访问
String savepath = this.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println(savepath);

2.为了防止上传名称相同的文件,可以使用UUID

    String savepath = this.getServletContext().getRealPath("/upload");
    String saveFilename = makeFileName(filename);  //得到文件保存的名称
    FileOutputStream out = new FileOutputStream(savepath + "\\" + saveFilename);  //向upload目录中写入文件
         。。。。。。。。。。。。。。。
?
public String makeFileName(String filename){  //2.jpg
        return UUID.randomUUID().toString() + "_" + filename;
}

3.防止一个文件夹下的文件太多(文件夹下文件过多,将导致打开缓慢)

    String savepath = this.getServletContext().getRealPath("/upload");
    String realSavePath = makePath(filename, savePath);  //得到文件的保存目录
    FileOutputStream out = new FileOutputStream(realSavePath + "\\" + filename);
?
public String makePath(String filename,String savePath){//文件的存放位置是根据文件名算出的,以后再下载的时候可以根据计算结果来确定文件存放的地址

    int hashcode = filename.hashCode();//拿到filename的地址
    int dir1 = hashcode&0xf;  //0--15,拿到低四位当一级目录
    int dir2 = (hashcode&0xf0)>>4;  //0-15,5到8位当二级目录

    String dir = savePath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
    File file = new File(dir);
    if(!file.exists()){//如果这个目录不存在,创建
        file.mkdirs();
    }
    return dir;
}

4.限制上传文件的大小

            upload.setFileSizeMax(1024);//单个文件不能超过1k
            upload.setSizeMax(1024*10);//总共不能超过10k
            List<FileItem> list = upload.parseRequest(request);
            for(FileItem item : list){
?
?
}catch (FileUploadBase.FileSizeLimitExceededException e) {
            e.printStackTrace();
            request.setAttribute("message", "文件超出最大值!!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return;
        }

5.监听文件上传进度

//2.得到解析器
ServletFileUpload upload = new ServletFileUpload(factory);      
?
upload.setProgressListener(new ProgressListener(){
    public void update(long pBytesRead, long pContentLength, int arg2) {
    System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
    }
});
?
upload.setHeaderEncoding("UTF-8");  //解决上传文件名的中文乱码

二、文件下载

文件下载列表:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>  
  <body>
?
    <c:forEach var="me" items="${map}">
        <c:url value="/servlet/DownLoadServlet" var="downurl">
            <c:param name="filename" value="${me.key}"></c:param>
        </c:url>
        ${me.value }  <a href="${downurl}">下载</a>  <br/>
    </c:forEach>
    
  </body>
</html>

查找所有文件:

//列出网站所有下载文件
public class ListFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String filepath = this.getServletContext().getRealPath("/WEB-INF/upload");
        Map map = new HashMap();
        listfile(new File(filepath),map);

        request.setAttribute("map", map);
        request.getRequestDispatcher("/listfile.jsp").forward(request, response);
    }

    public void listfile(File file,Map map){
        if(!file.isFile()){//如果不是文件,是文件夹
            File files[] = file.listFiles();
            for(File f : files){
                listfile(f,map);
            }
        }else{
            String realname = file.getName().substring(file.getName().indexOf("_")+1);  //9349249849-88343-8344_阿_凡_达.avi
            map.put(file.getName(), realname);//UUID,文件名
        }

    }


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

通过传过来的参数(文件名的UUID)来算出文件所在文件夹,并将其取出

public class DownLoadServlet extends HttpServlet {
?
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
?


        String filename = request.getParameter("filename");  //23239283-92489-阿凡达.avi
        filename = new String(filename.getBytes("iso8859-1"),"UTF-8");
        String path = makePath(filename,this.getServletContext().getRealPath("/WEB-INF/upload"));

        File file = new File(path + "\\" + filename);
        if(!file.exists()){
            request.setAttribute("message", "您要下载的资源已被删除!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return;
        }

        String realname = filename.substring(filename.indexOf("_")+1);
        response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));

        FileInputStream in = new FileInputStream(path + "\\" + filename);
        OutputStream out = response.getOutputStream();
        byte buffer[] = new byte[1024];
        int len = 0;
        while((len=in.read(buffer))>0){
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
    }


    public String makePath(String filename,String savePath){

        int hashcode = filename.hashCode();