struts文件下載機制

Struts2 中使用 type="stream" 的 result 進行下載便可。只用提供一個輸入流inputStream,剩下的輸出工做struts幫咱們作。javascript

例子一:html

1.能夠爲 stream 的 result 設定以下參數java

contentType: 結果類型
contentLength: 下載的文件的長度
contentDisposition: 設定 Content-Dispositoin 響應頭. 該響應頭指定響應是一個文件下載類型, 通常取值爲  attachment;filename="document.pdf".
inputName: 指定文件輸入流的 getter 定義的那個屬性的名字. 默認爲 inputStreamspring

這四個通常在getter方法中定義或者在execute方法執行時設置,並且不用聲明變量,直接getter方法,第一個字母大寫,例如public InputStream getInputStream()。

bufferSize: 緩存的大小. 默認爲 1024
allowCaching: 是否容許使用緩存
contentCharSet: 指定下載的字符集sql

這三個參數通常使用默認值或者在xml文件中配置。apache


以上參數能夠在 Action 中以 getter 方法的方式提供,也能夠經過配置配置,也能夠使用默認值。也能夠動態設置值,在execute方法中設置。瀏覽器

 

 1 package FileDownload;
 2 
 3 import java.io.FileInputStream;
 4 import java.io.InputStream;
 5 
 6 import javax.servlet.ServletContext;
 7 
 8 import org.apache.struts2.ServletActionContext;
 9 
10 import com.opensymphony.xwork2.ActionSupport;
11 
12 public class FileDownLoad extends ActionSupport {
13 
14     /**
15      * 
16      */
17     private static final long serialVersionUID = 1L;
18 
19     private String contentType;
20     private long contentLength;
21     private String contentDisposition;
22     private InputStream inputStream;
23     
24     
25     public String getContentType() {
26         return contentType;
27     }
28 
29 
30     public long getContentLength() {
31         return contentLength;
32     }
33 
34 
35 //    在getter方法中設置所須要的參數
36     public String getContentDisposition() {
37         contentDisposition = "attachment;filename=filesUp.html";
38         return contentDisposition;
39     }
40 
41 
42     public InputStream getInputStream() {
43         return inputStream;
44     }
45 
46 
47     @Override
48     public String execute() throws Exception {
49         
50         //肯定各個成員變量的值
51         contentType = "text/html";
52         
53         ServletContext servletContext = 
54                 ServletActionContext.getServletContext();
55         String fileName = servletContext.getRealPath("/files/filesUp.html");
56 //        打開輸入流
57         inputStream = new FileInputStream(fileName);
58         contentLength = inputStream.available();
59                 
60         
61         return super.execute();
62     }
63 }

上面能夠在execute方法執行時動態設置參數,也能夠在getter方法中設置參數。緩存

 

 

配置文件tomcat

 <!-- 文件下載 -->
        <action name="fileDownload" class="FileDownload.FileDownLoad">
            <result type="stream">
                <!-- 其餘的參數在類中設置或者使用默認 -->
                <param name="bufferSize">2048</param>
            </result>
        </action>

 

 例子二:安全

目錄結構:

 

動態將數據寫到Excel文件並提供下載:

package cn.xm.exam.action.exam.exam;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;

import cn.xm.exam.MyElFunction.MyElFunction;
import cn.xm.exam.service.exam.exam.ExamService;
import cn.xm.exam.service.grade.EmployeeExamService;
import jxl.common.Logger;

/**
 * 導出參考人信息 1.查出數據 2.寫入Excel 3.打開流,提供下載
 * 
 * @author QiaoLiQiang
 * @time 2017年10月29日下午10:29:51
 */
@Controller
@Scope("prototype")
@SuppressWarnings("all")
public class ExtExamEmployeesAction extends ActionSupport {
    private Logger logger = Logger.getLogger(FindExamAction.class);
    private String fileName;// 導出的Excel名稱
    @Resource
    private ExamService examService;// 考試service
    @Resource
    private EmployeeExamService employeeExamService;// 員工成績service

    // 1.查數據
    private String examId;// 考試ID(用於查詢考試員工)

    public List<Map<String, Object>> findExamEmployeeByExamId() {
        List<Map<String, Object>> employees = null;
        try {
            employees = employeeExamService.getEmployeeexamsByExamId(examId);
        } catch (SQLException e) {
            logger.error("導出考試人員異常", e);
        }
        return employees;
    }

    // 2.寫入Excel
    public boolean writeExamEmployees2Excel(List<Map<String, Object>> examEmployees, String fileName) {
        // 標題
        String[] title = { "序號", "姓名", "身份證號", "性別", "所屬部門", "員工類型", "考試方式" };
        // 建立一個工做簿
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 建立一個工做表sheet
        HSSFSheet sheet = workbook.createSheet();
        // 設置列寬
        setColumnWidth(sheet, 7);
        // 建立第一行
        HSSFRow row = sheet.createRow(0);
        // 建立一個單元格
        HSSFCell cell = null;
        // 建立表頭
        for (int i = 0; i < title.length; i++) {
            cell = row.createCell(i);
            // 設置樣式
            HSSFCellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 設置字體居中
            // 設置字體
            HSSFFont font = workbook.createFont();
            font.setFontName("宋體");
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 字體加粗
            // font.setFontHeight((short)12);
            font.setFontHeightInPoints((short) 13);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            cell.setCellValue(title[i]);
        }

        // 寫入數據
        // 從第二行開始追加數據
        for (int i = 1; i < (examEmployees.size() + 1); i++) {
            // 建立第i行
            HSSFRow nextRow = sheet.createRow(i);
            // 獲取數據
            Map<String, Object> employees = examEmployees.get(i - 1);
            for (int j = 0; j < 7; j++) {
                HSSFCell cell2 = nextRow.createCell(j);
                if (j == 0) {
                    cell2.setCellValue(j + 1);
                }
                if (j == 1) {
                    cell2.setCellValue(employees.get("employeeName").toString());
                }
                if (j == 2) {
                    cell2.setCellValue(employees.get("employeeId").toString());
                }
                if (j == 3) {
                    cell2.setCellValue(MyElFunction.replace(employees.get("sex").toString(), "12", "男女"));
                }
                if (j == 4) {
                    cell2.setCellValue(employees.get("departmentName").toString());
                }
                if (j == 5) {
                    cell2.setCellValue(
                            MyElFunction.replace(employees.get("employeeType").toString(), "01", "內外") + "部員工");
                }
                if (j == 6) {
                    cell2.setCellValue(employees.get("examMethod").toString());
                }
            }
        }

        // 建立一個文件
        File file = new File(fileName);
        // 若是存在就刪除
        if (file.exists()) {
            file.delete();
        }
        try {
            file.createNewFile();
            // 打開文件流
            FileOutputStream outputStream = FileUtils.openOutputStream(file);
            workbook.write(outputStream);
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    // 設置列寬()
    private static void setColumnWidth(HSSFSheet sheet, int colNum) {
        for (int i = 0; i < colNum; i++) {
            int v = 0;
            v = Math.round(Float.parseFloat("15.0") * 37F);
            v = Math.round(Float.parseFloat("20.0") * 267.5F);
            sheet.setColumnWidth(i, v);
        }
    }

    // 3.打開文件的流提供下載
    public InputStream getInputStream() throws Exception {
        this.create();// 建立文件到指定目錄下
        String path = ServletActionContext.getServletContext().getRealPath("/files/examEmployeesExcel");
        String filepath = path + "\\" + fileName + ".xls";
        File file = new File(filepath);
        // 只用返回一個輸入流
        return FileUtils.openInputStream(file);// 打開文件
    }

    // 產生Excel到文件夾下面
    public void create() {
        // 獲取工程下的路徑
        String path = ServletActionContext.getServletContext().getRealPath("/files/examEmployeesExcel");
        String filepath = path + "\\" + fileName + ".xls";
        // 獲取文件
        List<Map<String, Object>> examEmployees = this.findExamEmployeeByExamId();
        this.writeExamEmployees2Excel(examEmployees, filepath);
    }

    // 文件下載名
    public String getDownloadFileName() {
        String downloadFileName = "";
        String filename = fileName + ".xls";
        try {
            downloadFileName = URLEncoder.encode(filename, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return downloadFileName;
    }

    @Override
    public String execute() throws Exception {
        // 先將名字設爲秒數產生惟一的名字
        this.setFileName(String.valueOf(System.currentTimeMillis()));
        return super.execute();
    }

    // get,set方法
    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getExamId() {
        return examId;
    }

    public void setExamId(String examId) {
        this.examId = examId;
    }

}

 

 

 配置文件:

        <!-- 導出參考人員信息 -->
        <action name="exportExamEmployees" class="extExamEmployeesAction">
            <result type="stream">
                <!-- 其餘的參數在類中設置或者使用默認 -->
                <param name="contentType">application/octet-stream</param>
                <param name="inputName">inputStream</param>
                <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
                <param name="bufferSize">8192</param>
            </result>
        </action>

 

 ${downloadFileName}會調用getDownloadFileName()方法

 

 例子三:

目錄結構:

 

1.前臺JS

<script type="text/javascript">
    function down(flag) {
        if (flag == 1) {
            if (confirm("肯定下載谷歌瀏覽器?")) {
                window.location.href = "export_execute.action?name=ChromeStandalone_56.0.2924.87_Setup.exe"
            }
        }
        if (flag == 2) {
            if (confirm("肯定下載火狐瀏覽器?")) {
                window.location.href = "export_execute.action?name=Firefox-57.0.2.6549-setup.exe"
            }
        }
        if (flag == 3) {
            if (confirm("肯定下載操做手冊?")) {
                window.location.href = "export_execute.action?name=《安全培訓管理系統》用戶考試操做手冊.pdf"
            }
        }
    }
</script>

 

2.後臺Action(tomcat編碼是UTF-8)

package cn.xm.exam.action.exam.exam;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 下載專區的下載文件
 * 
 * @author QiaoLiQiang
 * @time 2017年12月14日上午10:06:41
 */
@Controller // 控制層
@Scope("prototype") // 單例模式
@SuppressWarnings("all") // 壓制警告
public class ExtDownloadFile extends ActionSupport {
    // 注入服務器目錄地址
    private String serverPath;// 注入要下載的文件的地址
    // 接收文件名
    private String name;// struts的屬性驅動

    public void setServerPath(String serverPath) {
        this.serverPath = serverPath;
    }

    public String getServerPath() {
        return serverPath;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // 須要提供給struts寫出數據的輸入流
    public InputStream getInputStream() {
        try {
            // 轉碼:解決中文亂碼問題
            // 先用ISO8859-1編碼 再使用UTF-8解碼
            // String filename = new
            // String(name.getBytes("ISO8859-1"),"UTF-8");//中名名稱.後綴名
            String filename = name;
            String path = ServletActionContext.getServletContext().getRealPath(serverPath);
            FileInputStream fis = new FileInputStream(new File(path + "\\" + filename));// 服務器目錄地址+文件名
            name = new String(name.getBytes("UTF-8"), "ISO8859-1");
            return fis;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

    }

    // 下載方法
    public String execute() {
        return SUCCESS;
    }
}

 

3.配置:

        <!-- 下載專區的文件下載 -->
        <action name="export_*" class="extDownloadFile">
            <!-- 爲setServerPath方法中的serverPath屬性注入值 也就是文件存放的地址/目錄(文件應該從哪裏下載) -->
            <param name="serverPath">/files/downloadFiles</param>
            <!-- 文件下載的關鍵:視圖類型必定是stream -->
            <result type="stream">
                <!-- 往StreamResult類中的屬性注入內容 -->
                <!-- 返回給瀏覽器的文件類型。返回通用的二進制 -->
                <param name="contentType">application/octet-stream</param>
                <!-- 返回給瀏覽器的輸入流 -->
                <!-- 默認就是 inputStream,它將會指示 StreamResult 經過 inputName 屬性值的 getter 方法, 
                    好比這裏就是 getInputStream() 來獲取下載文件的內容,意味着你的 Action 要有這個方法 -->
                <param name="inputName">inputStream</param>
                <!-- 告訴瀏覽器的方式下載資源 ${name}:獲取Action中getName()方法的數據 -->
                <!-- 默認爲 inline(在線打開),設置爲 attachment 將會告訴瀏覽器下載該文件,filename 指定下載文 件保存的文件名,若未指定將會是以瀏覽的頁面名做爲文件名,如以 
                    download.action 做爲文件名, 這裏使用的是動態文件名,${name}, 它將經過 Action 的 getName() 得到文件名 -->
                <param name="contentDisposition">attachment;filename=${name}</param>
                <!-- 緩存大小 -->
                <param name="bufferSize">1024</param>
            </result>
        </action>

 

【當你用心寫完每一篇博客以後,你會發現它比你用代碼實現功能更有成就感!】
相關文章
相關標籤/搜索