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>