zoukankan      html  css  js  c++  java
  • 文件上传和下载

      基本的文件上传:

        最基本的文件上传是在不利用其它额外jar包的帮助下,实现上传,这就是其它jar包封装的基础。

        我们在文件上传的时候大多都是利用表单里面的input标签,input标签里面有个type为file,就是定义了一个上传文件的输入框,现在我们要了解的是form表单的enctype属性,这个属性决定的是表单发到服务器之前如何对数据进行编码。

        enctype属性有三个值可取:

          1.application/x-www-form-urlencoded,是表单该属性的默认值,意思是发到服务器之前对所有的数据进行编码。

          2.multipart/form-data,意思是不对字符进行编码,如果你要上传文件,必须用这个值。

          3.text/plain,意思空格转换为 "+" 加号,但不对特殊字符编码。

    下面我们写个简单的html文件,定义一个表单,用input标签进行文件上传:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>file.html</title>
        
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="this is my page">
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      </head>
      <body>
        <form action="dealFile.jsp" enctype="multipart/form-data" method="post">
            上传文件:<input type="file" name="file" /><br>
            姓名:<input type="text" name="name" /><br>
            <input type="submit" value="提交"/>
        </form>
      </body>
    </html>

        我们都知道,表单的数据是通过http协议传给服务器的,所以服务器的处理也是从http协议中获取数据,对其进行解析,request对象中有一个getInputStream方法,这个方法可以得到一个输入流,从这个流中我们就可以读取到文件的内容,当然也包括其他表单附带的数据:

    dealFile.jsp:

    <%@ page language="java" import="java.util.*, java.io.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'dealFile.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
      </head>
      <body>
        <% 
            request.setCharacterEncoding("UTF-8");
            InputStream is = request.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String buffer = null;
            out.println(buffer == null);
            while((buffer = br.readLine()) != null) {
                out.println(buffer + "<br>");
            }
        %>
      </body>
    </html>

      下面介绍使用Common-FileUpload框架进行上传,首先你必须引进两个jar包,一个是Commons-FileUpload.jar和Commons-io.jar,这两个jar包百度都可以搜索到:

      我们使用的还是上面的file.html,把它的action改为dealFileByFU.jsp:

    dealFileByFU.jsp:

    <%@page import="org.apache.commons.fileupload.FileItem"%>
    <%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
    <%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
    <%@ page language="java" import="java.util.*, java.io.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'dealFile.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <% 
            //定义上传工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //设置工厂的大小限制
            factory.setSizeThreshold(1024*1024*20);
            //设置文件的存放路径
            factory.setRepository(new File(request.getRealPath("/")));
            //根据工厂创建一个上传文件的ServletFileUpload对象
            ServletFileUpload upload = new ServletFileUpload(factory);
            //设置最大的上传限制
            upload.setSizeMax(1024*1024*20);
            //根绝request对其进行解析,items是所有的表单项
            List items = upload.parseRequest(request);
            //遍历所有的表单项
            for(Iterator it = items.iterator(); it.hasNext();) {
                FileItem item = (FileItem)it.next();
                //判断是普通的表单域还是上传文件域
                if(item.isFormField()) {
                    //拿到对应的字段名和值
                    String name = item.getFieldName();
                    String value = item.getString("UTF-8");
                    out.print(name + " = " + value);
                } else {
                    //拿到字段名
                    String fieldName = item.getFieldName();
                    //拿到文件名
                    String fileName = item.getName();
                    //拿到文件类型
                    String contentType = item.getContentType();
                    //命名文件名
                    FileOutputStream fos = new FileOutputStream(request.getRealPath("/")
                            + System.currentTimeMillis() + 
                            fileName.substring(fileName.lastIndexOf("."), fileName.length()));
                    //判断内存中是否有该文件
                    if(item.isInMemory()) {
                        fos.write(item.get());
                    } else {
                        InputStream is = item.getInputStream();
                        byte[] buffer = new byte[1024];
                        int len;
                        while((len = is.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                        is.close();
                        fos.close();
                    }
                }
            }
        %>
      </body>
    </html>

       接下来介绍的是另外一个小框架COS进行上传,首先我们同样要引入cos.jar包,COS的核心类是MultipartParser,该类用于解析HttpServletRequest请求,取出所有的表单域,每个表单域对应一个Part示例,通过这个Part我们就可以判断这个域是普通的表单域还是文件域。

    dealFileByCOS.jsp:

    <%@page import="com.oreilly.servlet.multipart.FilePart"%>
    <%@page import="com.oreilly.servlet.multipart.ParamPart"%>
    <%@page import="com.oreilly.servlet.multipart.Part"%>
    <%@page import="com.oreilly.servlet.multipart.MultipartParser"%>
    <%@ page language="java" import="java.util.*, java.io.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'dealFile.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <% 
            //使用MultipartParser解析request并且设置最大容量为10M
            MultipartParser mp = new MultipartParser(request, 10*1024*1024);
            //一个part就代表着一个表单域
            Part part;
            while((part = mp.readNextPart()) != null) {
                //取得所有表单域的name的属性值
                String name = part.getName();]
                //判断是普通的表单域还是文件域
                if(part.isParam()) {
                    //强制转化为普通的表单域
                    ParamPart paramPart = (ParamPart)part;
                    String value = paramPart.getStringValue("UTF-8");
                    out.println("Parm: " + name + " = " + value);
                    //String value = paramPart.
                } else if(part.isFile()) {
                    //强制转化为普通的文件域
                    FilePart filePart = (FilePart)part;
                    String fileName = filePart.getFileName();
                    if(fileName != null) {
                        //写进文件中
                        FileOutputStream fos = new FileOutputStream(request.getRealPath("/")
                                + System.currentTimeMillis() + 
                                fileName.substring(fileName.lastIndexOf("."), fileName.length()));
                        InputStream is = filePart.getInputStream();
                        byte[] buffer = new byte[1024];
                        int len;
                        while((len = is.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                        is.close();
                        fos.close();
                    }
                } else {
                    out.println("file : name " + name);
                }
                out.flush();
            }
        %>
      </body>
    </html>

      下面介绍Struts2的文件上传,使用Struts框架进行解析,更加的方便,因为里面已经为我们封装好了实现,但是我们千万不要以为Struts里面的全部上传文件都是自己实现的,它里面也是使用小框架实现的,只是它做了更近一步的封装。

      在Struts2的default.properties配置文件中,我们可以看到:

      所以我们可以发现你导入struts2的jar包的时候是需要导入commons-io.jar和common-fileupload.jar的,struts2默认是使用FileUpload框架。

      下面我们写一个action对应我们的表单域:

    package com.xujianguo.action;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    
    import org.apache.struts2.ServletActionContext;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    @SuppressWarnings("all")
    public class FileUpload extends ActionSupport {
        private String name;
        private File upload;
        private String uploadContentType;
        private String uploadFileName;
        private String savePath;
        
        public String execute() throws Exception {
            FileOutputStream fos = new FileOutputStream(getSavePath() + "\" + getUploadFileName());
            FileInputStream fis = new FileInputStream(getUpload());
            byte[] buffer = new byte[1024];
            int len = 0;
            while((len = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, len);
            }
            return SUCCESS;
        }
        
        public void setSavePath(String value) {
            this.savePath = value;
        }
        
        public String getSavePath() {
            return ServletActionContext.getRequest().getRealPath(savePath);
        }
        
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name= name;
        }
        
        public File getUpload() {
            return upload;
        }
        
        public void setUpload(File upload) {
            this.upload = upload;
        }
    
        public String getUploadContentType() {
            return uploadContentType;
        }
    
        public void setUploadContentType(String uploadContentType) {
            this.uploadContentType = uploadContentType;
        }
    
        public String getUploadFileName() {
            return uploadFileName;
        }
    
        public void setUploadFileName(String uploadFileName) {
            this.uploadFileName = uploadFileName;
        }
    }

       这里必须提醒的是:File类型的变量是对应的表单中input类型为file的name属性的值,其他属性如uploadFileName和uploadContentType都是以它为基础的。

    struts.xml中的action配置:

    <action name="upload" class="com.xujianguo.action.FileUpload">
        <param name="savePath">/upload</param>
        <result name="success">/showFile.jsp</result>
    </action>

     showFile.jsp:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
            上传成功<br>
            姓名:<s:property value="name"/><br>
            文件为:<img src="<s:property value="'upload/' + uploadFileName" />"/>
      </body>
    </html>

       使用拦截器实现文件过滤:

        Struts2提供了一个文件上传的拦截器-fileUpload,为了让该拦截器起作用,只需要要action中配置一下就ok了,它有两个参数:

          allowedTypes:该参数指定允许上传文件的类型

          maximumSize:该参数指定上传文件的大小,单位为字节。

    struts.xml配置:

    <action name="upload" class="com.xujianguo.action.FileUpload">
                <interceptor-ref name="fileUpload">
                    <param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg</param>
                    <param name="maximumSize">200000</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <param name="savePath">/upload</param>
                <result name="success">/showFile.jsp</result>
                <result name="input">/file.html</result>
    </action>

      Struts2多文件上传:

        其实多文件上传跟单文件上传是同样的道理,只是你的Action方面就不能单用一个File类型去接受多个文件了,我们可以改成List<File>对应去存储文件,修改后的文件为:

    package com.xujianguo.action;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.util.List;
    
    import org.apache.struts2.ServletActionContext;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    @SuppressWarnings("all")
    public class MultiFileUpload extends ActionSupport {
        private String name;
        private List<File> upload;
        private List<String> uploadContentType;
        private List<String> uploadFileName;
        private String savePath;
        
        public String execute() throws Exception {
            List<File> files = getUpload();
            for(int i = 0; i < files.size(); i++) {
                FileOutputStream fos = new FileOutputStream(getSavePath() + "\" + getUploadFileName().get(i));
                FileInputStream fis = new FileInputStream(files.get(i));
                byte[] buffer = new byte[1024];
                int len = 0;
                while((len = fis.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
            }
            return SUCCESS;
        }
        
        public void setSavePath(String value) {
            this.savePath = value;
        }
        
        public String getSavePath() {
            return ServletActionContext.getRequest().getRealPath(savePath);
        }
        
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name= name;
        }
    
        public List<File> getUpload() {
            return upload;
        }
    
        public void setUpload(List<File> upload) {
            this.upload = upload;
        }
    
        public List<String> getUploadContentType() {
            return uploadContentType;
        }
    
        public void setUploadContentType(List<String> uploadContentType) {
            this.uploadContentType = uploadContentType;
        }
    
        public List<String> getUploadFileName() {
            return uploadFileName;
        }
    
        public void setUploadFileName(List<String> uploadFileName) {
            this.uploadFileName = uploadFileName;
        }
    }

      其他方面跟单文件的一致,哈哈,是不是很简单呢,不要给多文件吓到了。

      Struts2的文件下载:

        文件下载也是很简单的,我们简单的演示一下,首先是前端的页面:

    <a href="/Struts2Demo/guo/download.action">图片下载</a>

         前端最核心的就是这一句,访问action,让Struts去处理诸如文件名为中文之类的麻烦问题,接下来就是要配制我们的struts.xml:

            <action name="download" class="com.xujianguo.action.DownloadFile">
                <result name="success" type="stream">
                    <param name="contentType">image/png</param>
                    <param name="contentDisposition">attachment;filename="Snap1.png"</param>
                    <param name="inputName">input</param>
                </result>
            </action>

        我们一一来看里面的属性:

          stream:如果你的要实现文件下载,就必须使用type为stream的result,就是使用一个流。

          contentType:指定你下载文件的类型,我这里是image,如果你要的是文本的话就使用text/plain。

          contentDisposition:这里指定的是文件名和文件的下载方式,我使用的附件的形式,也就是attachment。

          inputName:指定你对应action里面的类型为InputStream的属性,指定的文件的流的获取。

        DownloadFile.java:

    package com.xujianguo.action;
    
    import java.io.InputStream;
    
    import org.apache.struts2.ServletActionContext;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    @SuppressWarnings("serial")
    public class DownloadFile extends ActionSupport {
        public InputStream input;
        
        public InputStream getInput() {
            return ServletActionContext.getServletContext().getResourceAsStream("/upload/Snap1.png");
        }
        
        public void setInput(InputStream input) {
            this.input = input;
        }
        
        public String execute() {
            return SUCCESS;
        }
    }
  • 相关阅读:
    poj 2763 Housewife Wind
    hdu 3966 Aragorn's Story
    poj 1655 Balancing Act 求树的重心
    有上下界的网络流问题
    URAL 1277 Cops and Thieves 最小割 无向图点带权点连通度
    ZOJ 2532 Internship 网络流求关键边
    ZOJ 2760 How Many Shortest Path 最大流+floyd求最短路
    SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流
    怎么样仿写已知网址的网页?
    5-10 公路村村通 (30分)
  • 原文地址:https://www.cnblogs.com/rayguo/p/3634497.html
Copyright © 2011-2022 走看看