java资料收集java学习

28、文件上传和下载(JavaEE笔记)

2016-06-04  本文已影响1082人  yjaal

一、文件上传概述

fileupload组件工作流程.png

二、相关示例

2.1示例一

UploadServlet1.java

package cn.itcast.web.servlet;
//文件上传,这里我们还是用的commons-fileupload和commons-io,但是tomcat中已经包含了相关的文件上传的包
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.RequestContext;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
*/
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet1 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String savaPath = this.getServletContext().getRealPath("/WEB-INF/upload");//得到文件的保存目录,而这个目录一般不允许被人随意访问,所以应该放在WEB-INF下
        //request.setCharacterEncoding("UTF-8");//这种方式不能解决提交的数据的乱码问题.表单为文件上传设置Request编码无效,只能手工设置
        try{
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //缓冲区默认是10k,下面我们设置如果上传文件超过10k则使用一个临时文件保存
            factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp")));
            
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setProgressListener(//这里我们定义一个监听器,可以看到文件上传的进度,之后可以使用ajax生成一个进度条,同时注意定义的位置,这里是在解析器定义之后解析完文件之前
                    new ProgressListener() {
                        
                        @Override
                        public void update(long pBytesRead, long pContentLength, int arg2) {
                            System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
                            
                        }
            });
            
            upload.setHeaderEncoding("UTF-8");//解决上传文件名在中文乱码问题
            
            if(!upload.isMultipartContent(request)){//如果不是文件上传
                //按照传统方式获取数据
                return ;
            }
            /*upload.setFileSizeMax(1024);//上传的文件不能超过1k
            upload.setSizeMax(1024*10);//上传文件的总大小不能超过10k
*/          List<FileItem> list = upload.parseRequest(request);
            for(FileItem item : list){
                if(item.isFormField()){
                    //fileItem中封装的是普通输入项的数据
                    String name = item.getFieldName();
                    
                    //String value = item.getString();
                    //value = new String(value.getBytes("iso8859-1"),"UTF-8");//由于对Request设置编码无效,这里我们只能手工设置
                    String value = item.getString("UTF-8");//也可以用这种方式制定码表
                    System.out.println(name + "=" + value);
                    
                }else{//提交的表单是上传文件,不是普通输入项
                    //request.getParameter("username");//这种方式是获取不到数据的,因为表单提交时以multipart/form-data形式提交的
                    String filename = item.getName();//注意:不同浏览器提交文件的方式是不一样的,有的是完整路径,但是有的是直接提交1.txt,所以这里我们需要作相应的截取工作
                    if(filename == null || filename.trim().equals("")){
                        continue;//如果某个框中没有选择上传的文件则跳出本次循环,继续下一次循环
                    }
                    
                    filename = filename.substring(filename.lastIndexOf("\\") + 1);
                    InputStream in = item.getInputStream();
                    String saveFileName = makeFileName(filename);//得到文件保存的名称
                    
                    String realSavaPath = makePath(saveFileName, savaPath);//产生目录
                    FileOutputStream out = new FileOutputStream(realSavaPath + "\\" + saveFileName);
                    byte buffer[] = new byte[1024];
                    int len = 0;
                    while((len = in.read(buffer)) > 0){
                        out.write(buffer, 0, len);
                    } 
                    in.close();
                    out.close();
                    item.delete();//删除临时文件,而且这行代码必须在上面流关闭的后面
                }
            }
        }catch(FileUploadBase.FileSizeLimitExceededException e){
            e.printStackTrace();
            request.setAttribute("message", "文件超出最大值");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return ;
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    //产生唯一的文件名
    public String makeFileName(String filename){

        return UUID.randomUUID().toString() + "_" + filename;
    }
    //产生一个目录
    public String makePath(String filename, String savePath){
        int hashCode = filename.hashCode();//得到一个文件名的哈希编码,即文件在内存中的地址
        int dir1 = hashCode & 0xf;//得到一个0-15的数,表示一级目录最多有16个目录
        int dir2 = (hashCode & 0xf0) >> 4;
        
        String dir = savePath + "\\" + dir1 + "\\" + dir2;//完整路径就是upload\2\3...
        File file = new File(dir);
        if(!file.exists()){
            file.mkdirs();//因为这里会有多级目录,则用此方法。若是只有一级目录,那使用mkdir方法
        }
        return dir;
    }

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

上传页面:upload.jsp

<body>
    <form action="${pageContext.request.contextPath }/servlet/UploadServlet1" 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>
  </body>

说明:

注意:

factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp")));

但是一般来说,文件会先保存在临时文件中,之后才会从临时文件复制到真正的存储目录中,而且这个临时文件一般不会删除,这里我们需要设置让其删除,如下。

if(filename == null || filename.trim().equals("")){
        continue;//如果某个框中没有选择上传的文件则跳出本次循环,继续下一次循环
}
<body>
  <!-- 如果想提交则在下面套一个form表单 ,同时如果是上传文件的话一定要注意其enctype="mutlipart/form-data"-->
  <!-- <form action="" enctype="mutlipart/form-data"> -->
    <table>
        <tr>
            <td>上传用户:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>上传文件:</td>
            <td><input type="button" value="添加上传文件" onclick="addInput()"></td>
        </tr>
        <tr>
            <td>    </td>
            <td>
                <div id="file">
                    
                </div>
            </td>
        </tr>
    </table>
    <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>
  </body>

三、文件下载

3.1 概述

3.2 示例

列出网站所有文件:ListFileServlet.java

package cn.itcast.web.servlet;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//列出网站所有的下载文件
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){
        
        //为了让迭代出来的文件进行显示,这里我们一般传递一个map进行保存
        if(!file.isFile()){//如果是目录(不是文件)
            File files[] = file.listFiles();//得到所有文件或目录
            for(File f : files){
                listFile(f, map);
            }
        }else{//将迭代出的文件在jsp页面中进行显示
            String realname = file.getName().substring(file.getName().indexOf("_") + 1);
            map.put(file.getName(), realname);//强文件在硬盘中的名称作为key,而真实名称作为value
        }
    }

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

下载界面:listfile.jsp

<c:forEach var="me" items="${map }"><%-- filename=${me.key} 这里不能这样做,因为key中包含了中文--%>
        <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>

DownLoadServlet.java

package cn.itcast.web.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
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 {
        String filename = request.getParameter("filename");
        //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"));
        //这里注意:URLEncoder.encode对IE是有效的,但是对火狐无效
        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();//得到一个文件名的哈希编码,即文件在内存中的地址
        int dir1 = hashCode & 0xf;//得到一个0-15的数,表示一级目录最多有16个目录
        int dir2 = (hashCode & 0xf0) >> 4;
            
        String dir = savePath + "\\" + dir1 + "\\" + dir2;//完整路径就是upload\2\3...
        File file = new File(dir);
        if(!file.exists()){
            file.mkdirs();//因为这里会有多级目录,则用此方法。若是只有一级目录,那使用mkdir方法
        }
        return dir;
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读