(十)文件上传与下载

  •   文件上传的几种方式:

  1.   上传到服务器的文件夹中。(不重要的文件),一般在数据库中只存文件的路径和文件名。
  2.    上传到数据库的字段中。(重要的文件),在字段中以二进制的形式存储。

一、上传到服务器的文件夹中。

  • 前提:

  • index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix="s"  uri="/struts-tags"  %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<% String path=request.getContextPath(); %>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
        <h2>上传到文件夹</h2>
<form action="uploadAction/upload!upload_toFolder" enctype="multipart/form-data" method="post">
    <table border="1" width="50%" height="50%">
    
    <tr>
        <td>ID:</td>
        <td><s:textfield name="id"></s:textfield></td>
    </tr>    
    <tr>    
        <td>文件:</td>
        <td><s:file name="file" ></s:file></td>
    </tr>    
    <tr>
        <td><s:submit value="提交"></s:submit></td>
    </tr>    
    
</table>
</form>

        <h2>上传到服务器</h2>
<form action="uploadAction/upload!upload_to_table" enctype="multipart/form-data" method="post">
    <table border="1" width="50%" height="50%">
    
    <tr>
        <td>ID:</td>
        <td><s:textfield name="id"></s:textfield></td>
    </tr>    
    <tr>    
        <td>文件:</td>
        <td><s:file name="file" ></s:file></td>
    </tr>    
    <tr>
        <td><s:submit value="提交"></s:submit></td>
    </tr>    
    
</table>
</form>
</body>
</html>
  • struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

      <constant name="struts.i18n.encoding" value="UTF-8"></constant>
    <constant name="struts.multipart.maxSize" value="209715200"></constant>
    <constant name="struts.action.extension" value="action,,"></constant>
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <constant name="struts.devMode" value="true" />
    <constant name="struts.i18n.reload" value="true"></constant>
    <constant name="struts.ui.theme" value="simple" />
    <constant name="struts.configuration.xml.reload" value="true"></constant>
    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
    <constant name="struts.handle.exception" value="true"></constant>

    <package name="default" namespace="/uploadAction" extends="struts-default">
        <action name="upload" class="action.FileUpload">
            <result name="list">/list.jsp</result>
        </action>
    </package>
 
     <package name="download" namespace="/download" extends="struts-default" >
         <action name="downloadAction" class="action.DownLoadAction">
                 <result name="down_for_struts" type="stream">
                     <param name="bufferSize">10240</param>
                    <param name="contentType">
                        application/octet-stream
                    </param>
                    <param name="contentDisposition">
                        attachment;filename=${encode_filename}   <!-- ${} OGNL表达式,只用于xml文件中获取广义值栈的值 -->
                    </param>
                    <param name="contentCharSet">ISO-8859-1</param>
                    <param name="inputName">fileInput</param>
                 </result>
         </action>
     
     </package>
 
</struts>
  • FileUpload 。java
package action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Connection;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.io.FileUtils;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import DBUtils.DButil;
import Global.Global;
import actionUtil.BaseAction;

public class FileUpload extends BaseAction {

    private static final long serialVersionUID = 1L;
    /* ============================================== */
    private int id; // 用于接收表单中的id
    private File file; // 用于接收表单的文件
    private String fileFileName; // 控件名称+FileName 用于获取上传文件的名。
    private String fileContentType; // 控件名称+ContentType 用于获取文件的类型,比如txt、word等
    
    private String fileName="";
    private String filePath="";

    public String getFileContentType() {
        return fileContentType;
    }
    public void setFileContentType(String fileContentType) {
        this.fileContentType = fileContentType;
    }
    public String getFileFileName() {
        return fileFileName;
    }
    public void setFileFileName(String fileFileName) {
        this.fileFileName = fileFileName;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public File getFile() {
        return file;
    }
    public void setFile(File file) {
        this.file = file;
    }

    /* ============================================== */
    @Override
    public String execute() {

        return "success";
    }

    /**
     * 文件上传到服务器中的文件夹里。
     * 1. 当用户成功上传文件或者上传失败的时候会有javaScript的alert提示,那么这个方法的返回值只能是null,否则脚本将无法运行。
     * @return
     */
    public String upload_toFolder() {
            
        if(fileFileName!=null && !fileFileName.equals("")){
            //如果文件名不为null或者不为空,说明用户有上传文件,需要处理文件上传
            fileName=this.getFileFileName();
            boolean isuploaderror=true;
            String errorMsg="";  //错误消息
            try {
                String uploadpath=this.context.getRealPath("/upload"); //获取存放用户文件的文件夹路径
                File destFile=new File(uploadpath+"/"+this.fileFileName); //存放到文件夹里的用户上传文件
                FileUtils.copyFile(file, destFile); //FileUtils文件工具类的copyFile可以一个文件的拷贝到另一个文件。
                filePath=fileName;
            
                isuploaderror=false;
            } catch (Exception e) {
                e.printStackTrace();
                errorMsg=e.getMessage();
            } 
            
            if(isuploaderror == true){
                //说明上传错误,数据库不能记录
                Global.WebErrorMsg(response, errorMsg);
                
            }else{
                //上传正确,记录到数据库
                String sql="insert into file(id,filename,filepath) values('"+this.id+"','"+this.fileFileName+"','"+filePath+"')";
            boolean flag=false;
            
            try {
                flag = DButil.uptData(sql);
            } catch (Exception e) {
                errorMsg=e.getMessage();  //如果上传错误,就把错误消息赋给errorMsg,前提是try里面的uptData方法定义里把异常抛出且uptData方法里的catch块里有把throw e即把异常对象抛出,否则这里的e.getMessage()就没有异常消息内容。                    
                e.printStackTrace();
            }
        
                if(flag==true){
                    //文件数据成功存入数据库
                    String ListURL=request.getContextPath()+"/uploadAction/upload!list"; //跳转到显示全部文件记录的页面
                    out.print("<script lang='javascript'>");
                    out.println("alert('文件数据存入成功')");
                    out.println("window.location.href='"+ListURL+"'");
                    out.print("</script>");
                }else{
                    //文件数据存入数据库失败,返回上一页。
                    Global.WebErrorMsg(response, errorMsg);
                }                    
            }        
        }    
        return null;   
    }
    
    /**
     * 以二进制形式上传到数据库的字段中。
     * 前提:
     * 1. jdk 1.6 以上版本。
     * 2. 必须要用prepare的Statement语句,否则操作不成功。
     * 3. 当用户成功上传文件或者上传失败的时候会有javaScript的alert提示,那么这个方法的返回值只能是null,否则脚本将无法运行。
     * @return
     */
    public String upload_to_table() {
        InputStream inputStream=null;
        if(fileFileName!=null && !fileFileName.equals("")){
            //如果文件名不为null或者不为空,说明用户有上传文件,需要处理文件上传
            fileName=this.getFileFileName();
            String errorMsg="";  //错误消息
            try {
                inputStream=new FileInputStream(this.file);
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            }
                //上传正确,记录到数据库
                String sql="insert into file(id,filename,filedata) values(?,?,?)";
            boolean flag=false;
            Connection conn=null;
            PreparedStatement pstat=null;
            try {
                conn=DButil.getConn();
                conn.setAutoCommit(false);  //当用户上传数据的时候禁止事务的自动提交
                pstat= conn.prepareStatement(sql);
                pstat.setInt(1, this.id);
                pstat.setString(2, this.fileFileName);
                pstat.setBinaryStream(3, inputStream);
                pstat.executeUpdate();
                flag=true;
                conn.commit();    //提交事务
    
            } catch (Exception e) {
                try {
                    conn.rollback();//有异常就回滚事务。
                } catch (SQLException e1) {
            
                    e1.printStackTrace();
                }   
                flag=false;
                errorMsg=e.getMessage();  //如果上传错误,就把错误消息赋给errorMsg,前提是try里面的uptData方法定义里把异常抛出且uptData方法里的catch块里有把throw e即把异常对象抛出,否则这里的e.getMessage()就没有异常消息内容。                    
                e.printStackTrace();
            }    
                if(flag==true){
                    //文件数据成功存入数据库
                    String ListURL=request.getContextPath()+"/uploadAction/upload!list"; //跳转到显示全部文件记录的页面
                    out.print("<script lang='javascript'>");
                    out.println("alert('文件数据存入成功')");
                    out.println("window.location.href='"+ListURL+"'");
                    out.print("</script>");
                }else{
                    //文件数据存入数据库失败,返回上一页。
                    Global.WebErrorMsg(response, errorMsg);
                }
            }    
        return null;   
    }
    
    
    /**
     *生成文件数据库中所有文件的列表,以提供用户下载 
     * @return
     */
    
    public String list() throws Exception {
        //导入commons-dbutils-1.3.jar 使用里面的查询类实现快速查询
        QueryRunner run=new QueryRunner();
        
        String sql="select id,filename,filepath from file ";
        Connection    conn=DButil.getConn();
        List<Map<String, Object>> fileList =run.query(conn, sql, new MapListHandler());
        ActionContext actionContext=ActionContext.getContext();
        ValueStack valueStack=actionContext.getValueStack();
        
        valueStack.set("map", fileList);    
        return "list";
    }

}
  • list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<%String path=request.getContextPath(); %>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<s:debug></s:debug>
        <table border="1" width="100%">
            <tr>
                <th>id</th>
                <th>文件名</th>
                <th>文件路径</th>
                <th colspan="3">操作</th>
            </tr>
            
            <s:iterator value="map"  var="file" >
            <tr>
                <td><s:property value="#file.id" /></td>
                <td><s:property value="#file.filename" /></td>
                <td><s:property value="#file.filepath" /></td>
                <td><s:if test="#file.filepath!=null && #file.filename!='' ">
                <a href="<%=path%>/download/downloadAction!from_folder?id=<s:property value="#file.id" />">从文件夹下载</a>
                </s:if>&nbsp;
                </td>
                <td>
                <s:if test="#file.filename!='' &&(#file.filepath==null || #file.filepath=='' )">
                <a href="<%=path%>/download/downloadAction!from_table?id=<s:property value="#file.id" />">从数据库下载</a>
                </s:if>
                </td>
                <td><s:if test="#file.filepath!=null && #file.filename!='' ">
                <a href="<%=path%>/download/downloadAction!from_struts?id=<s:property value="#file.id" />">从struts下载</a>
                </s:if>&nbsp;</td>
            </tr>
            </s:iterator>
        </table>
</body>
</html>
  • DownLoadAction 。java
package action;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Map;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.io.IOUtils;

import DBUtils.DButil;
import actionUtil.BaseAction;

public class DownLoadAction extends BaseAction {

    @Override
    public String execute() throws Exception {

        return null;
    }

    /**
     * 从文件夹中下载文件 步骤: 1. 从数据库中根据客户端传来的id用找到这个文件 2. 定义response对象为二进制输出流 3.
     * 把文件的输入流拷贝到response输出流中。 注意:
     * 
     * @return
     */
    public String from_folder() throws Exception {
        int id = Integer.parseInt(request.getParameter("id"));
        String sql = "select filename,filepath from file where id='" + id + "'";
        Connection conn = null;
        String upload = context.getRealPath("/upload"); // 拿到存放文件的上传文件夹的路径
        String filepath = "";
        String filename = "";
        try {
            conn = DButil.getConn();
            QueryRunner run = new QueryRunner();
            Map<String, Object> map = run.query(conn, sql, new MapHandler());
            if (map != null) {
                filename = (String) map.get("filename");
                filepath = (String) map.get("filepath");

                File file = new File(upload + "/" + filepath); // 拿到用户想要下载的文件

                if (file.exists() == true) {
                    // 文件夹中有这个文件
                    InputStream fileinput = new FileInputStream(file); // 拿到用户想下载文件的输入流

                    /*
                     * 本类的response对象是BaseAction类中的response对象。这个对象定义了this.
                     * response.setContentType("text/html");
                     * 如果我们要想response返回的是文件流那么必修对这个对象进行重新定义。
                     */
                    response.reset();
                    response.setContentType("application/octet-stream"); // 表示输出的类型是流的数据类型。会弹出下载的窗口
                    String enco_filename = new String(filename.getBytes("GBK"), "ISO-8859-1"); // 设定下载窗口中显示文件名
                    response.setHeader("Content-Disposition", "attachment; filename="" + enco_filename + """);
                    OutputStream fileout = response.getOutputStream(); // 拿到response的输出流
                    // 文件输入流与response输出流的拷贝
                    int i = 0;
                    byte[] byteArray = new byte[10240];
                    while ((i = fileinput.read(byteArray)) != -1) {
                        fileout.write(byteArray, 0, i);
                        out.flush();
                    }

                    fileout.close(); // 输入输出流的关闭
                    fileinput.close();
                } else {
                    // 文件夹中没有这个文件
                    throw new RuntimeException("下载的文件不存在。");
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DButil.close(conn, null, null);

        }

        return null;
    }

    /**
     * 从数据库中下载文件
     * 
     * @return
     */

    public String from_table() {
        int id = Integer.parseInt(request.getParameter("id"));
        String sql = "select filename,filedata from file where id='" + id + "'";
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        String filename = "";
        try {
            conn = DButil.getConn();
            stat = conn.createStatement();
            rs = stat.executeQuery(sql);
            
            if (rs.next()) {
                filename = rs.getString("filename");
                String enco_filename = new String(filename.getBytes("GBK"), "ISO-8859-1"); // 设定下载窗口中显示文件名
                InputStream input = rs.getBinaryStream("filedata");

                if (input != null) {
                    /*
                     * 本类的response对象是BaseAction类中的response对象。这个对象定义了this.
                     * response.setContentType("text/html");
                     * 如果我们要想response返回的是文件流那么必修对这个对象进行重新定义。
                     */

                    response.reset();
                    response.setContentType("application/octet-stream"); // 表示输出的类型是流的数据类型。会弹出下载的窗口
                    response.setHeader("Content-Disposition", "attachment; filename="" + enco_filename + """);

                    OutputStream fileout = response.getOutputStream(); // 拿到response的输出流
                    // 文件输入流与response输出流的拷贝
                    int i = 0;
                    byte[] byteArray = new byte[10240];
                    while ((i = input.read(byteArray)) != -1) {
                        fileout.write(byteArray, 0, i);
                        out.flush();
                    }

                    fileout.close(); // 输入输出流的关闭
                    input.close();

                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DButil.close(conn, null, null);

        }

        return null;
    }

    /**
     * 1.以struts方式下载文件,与从文件夹下载类似,
     * 2.用户需要的文件不是以response方式返回而是以return到struts.xml中的result这个result以stream的方法返回结果<result name="down_for_struts" type="stream">
     * 3.在result中配置参数,即下载文件的相关信息。
     * 4.在开发中一般用从文件夹或者从服务器字段下载,而不用struts下载,因为如果文件名中含有空格那么这种方法无法显示空格以后的内容。
     * 5.如果在result中需要使用到action中的变量比如文件名、文件输入流等,需要把这些变量设为成员变量且定义getset方法
     * @return
     */
    private InputStream fileInput;
    private String encode_filename;


    public InputStream getFileInput() {
        return fileInput;
    }

    public void setFileInput(InputStream fileInput) {
        this.fileInput = fileInput;
    }

    public String getEncode_filename() {
        return encode_filename;
    }

    public void setEncode_filename(String encode_filename) {
        this.encode_filename = encode_filename;
    }

    public String from_struts() {
        int id = Integer.parseInt(request.getParameter("id"));
        String sql = "select filename,filepath from file where id='" + id + "'";
        Connection conn = null;
        String upload = context.getRealPath("/upload"); // 拿到存放文件的上传文件夹的路径
        String filepath = "";
        String filename = "";
        try {
            conn = DButil.getConn();
            QueryRunner run = new QueryRunner();
            Map<String, Object> map = run.query(conn, sql, new MapHandler());
            if (map != null) {
                filename = (String) map.get("filename");
                filepath = (String) map.get("filepath");

                File file = new File(upload + "/" + filepath); // 拿到用户想要下载的文件

                if (file.exists() == true) {
                    // 文件夹中有这个文件
            
                    encode_filename = new String(filename.getBytes("GBK"), "ISO-8859-1"); // 设定下载窗口中显示文件名
                    response.reset();
                    this.fileInput=new FileInputStream(file);
                
                    } 
                } else {
                    // 文件夹中没有这个文件
                    throw new RuntimeException("下载的文件不存在。");
                }

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

        return "down_for_struts";
    }
}
  • BaseAction.java
package actionUtil;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;

import com.opensymphony.xwork2.ActionSupport;

public abstract class BaseAction extends ActionSupport implements
        ServletRequestAware, ServletResponseAware, ServletContextAware {
    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected ServletContext context;
    protected HttpSession session;
    protected PrintWriter out;

    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
        if (this.request != null) {
            this.session = this.request.getSession();
        }
    }

    public void setServletResponse(HttpServletResponse response) {
        this.response = response;
        if (this.response != null) {
            try {
                this.response.setContentType("text/html");
                this.out = this.response.getWriter();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void setServletContext(ServletContext context) {
        this.context = context;
    }

    public abstract String execute() throws Exception;
}
  • DButil.java
package DBUtils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class DButil {
        
    private static final String DRIVER="com.mysql.jdbc.Driver"; 
    private static final String USER="root"; 
    private static final String PASSWD=""; 
    private static final String URL="jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=UTF-8"; 
    
    
    static{
    try{
        Class.forName(DRIVER);
        
    }catch(Exception e){
        throw new RuntimeException("无法加载驱动包");
    }
        
    }
    
    
    public static Connection getConn() {
        Connection conn=null;
        try {
            conn=DriverManager.getConnection(URL,USER,PASSWD);

        } catch (SQLException e) {

            e.printStackTrace();
        }
        return conn;
    }
    
    
    public static boolean uptData(String sql) throws Exception {
        Connection conn = null;
        Statement stmt = null;
        boolean flag = false;
        try {
            conn = DButil.getConn();
            stmt = conn.createStatement();
            stmt.executeUpdate(sql.toString());
            flag = true;
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
            throw e;
        } finally {
            DButil.close(conn, stmt, null);
        }
        return flag;
    }
    
    
    public static void close(Connection conn,Statement stat,ResultSet rs){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stat!=null){
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

    }
}
}
  • Global.java
package Global;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Global {
    public static void WebErrorMsg(HttpServletResponse resonse,String errorMsg)  {
        PrintWriter out;
        try {
            out = resonse.getWriter();
            out.print("<head>");
            out.print("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
            out.print("</head>");

            out.print("<script lang='javascript'>");
            out.println("window.alert("数据操作出现错误!原因 = " + errorMsg + "");");
            out.print("window.history.back();");
            out.print("</script>");

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

结果:

原文地址:https://www.cnblogs.com/shyroke/p/6592260.html