寫在前面:javascript
最近要作一個新的功能,點擊按鈕,能夠根據數據生成對應的xml文件並保存。下面記錄一下在作的過程的一些疑惑與問題(我就是太笨了,一些很簡單的知識都不知道,不過經過此次跟蛋蛋的交流,解決了個人不少疑惑~~~啊哈哈哈。。。)html
思考(作的過程當中的疑惑):java
1.如何將實體類轉成xml格式的文件?ajax
經查閱資料,生成xml格式的文件有不少種方法,dom、jdom、dom4j等,這裏我採用的是jdom,具體的生成xml格式的過程能夠看後面的代碼部分。瀏覽器
2.點擊按鈕能夠生成xml文件,這個是能夠作到的,可是在瀏覽器頁面上卻沒有彈出提示框讓用戶選擇文件的保存路徑,那麼這個彈出框是從哪裏來的呢?服務器
原來這個下載彈出框,是須要咱們在程序中設置的,就是須要咱們設置response的響應頭信息,設置以後,瀏覽器就會知道要彈出下載框。dom
3.這個功能跟文件下載功能有什麼區別?異步
沒有區別,生成xml文件,並保存,就是一個文件下載的功能jsp
4.什麼是文件下載?工具
文件下載的本質就是內容的輸出。內容從哪裏來?那麼既然說是內容的輸出,那這內容從何而來?大概有兩種方式,第一,讀取其餘文件的內容;第二,在程序中,建立出一個內容,例如,一個字符串。如何輸出?都說是輸出,那確定就是用OutputStream輸出流來輸出了。具體輸出到哪兒?這裏的輸出並非直接輸出到文件裏,而是把內容寫到response響應裏面,而後交給瀏覽器去作將內容寫入到文件裏的操做。
5.什麼是服務器內存?服務器磁盤?
服務器內存是內存,磁盤是磁盤,二者不可混淆,可是要明白一點,文件下載,首先是要將內容保存到服務器內存中,而後纔是從內存中寫入到磁盤中。
6.使用ajax請求進行文件下載能夠嗎?
不能夠的,由於ajax是異步的js,而js是不支持往磁盤裏寫東西的,因此響應流中的內容沒法被寫入到磁盤中,也就沒法實現下載。故這裏採用
window.location.href
來發送請求。可是使用ajax請求發送請求是能夠接收到響應的內容的。
好啦,在弄清楚了這些疑惑後,下面就開始具體的代碼實現過程嘍~
前臺jsp:
<%-- Created by IntelliJ IDEA. User: Eleven Date: 2018/1/3 Time: 10:07 To change this template use File | Settings | File Templates. --%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% String scheme = request.getScheme(); String serverName = request.getServerName(); String contextPath = request.getContextPath(); int port = request.getServerPort(); //網站的訪問跟路徑 String baseURL = scheme + "://" + serverName + ":" + port + contextPath; request.setAttribute("baseURL", baseURL); %> <html> <head> <title>生成xml文件</title> <script type="text/javascript"> function createXML(){ //發送請求到服務器 //!!!!對於文件的下載 不能使用ajax請求 由於ajax請求沒法實現文件的下載 window.location.href = '${baseURL}/createXML'; } </script> </head> <body> 點擊按鈕生成xml文件:<button id="btnClick" onclick="createXML();">生成xml文件</button> </body> </html>
後臺action:
/** * Description:com.ims.action * Author: Eleven * Date: 2018/1/2 9:56 */ @Controller("FileAction") public class FileAction extends BaseAction { /** * 文件下載的過程大體分爲三大步: * 1.設置response響應頭,告知瀏覽器是文件下載,並彈出那個文件保存的框框 * 2.獲取輸出的內容,並將要輸出的內容轉爲byte[]格式 * 3.輸出,將內容寫到響應中 */ public void createXML(){ //準備數據 Demo d = new Demo(); d.setDemoId(11); d.setDemoName("鳳姐"); Demo d2 = new Demo(); d2.setDemoId(22); d2.setDemoName("小花"); Demo d3 = new Demo(); d3.setDemoId(33); d3.setDemoName("狗子"); List<Demo> list = new ArrayList<Demo>(); list.add(d); list.add(d2); list.add(d3); //1.設置文件下載的response響應格式 String fileName = "demo"; //文件名 String fileType = "xml"; //文件類型 HttpServletResponse response = ServletActionContext.getResponse(); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + "." + fileType); response.setContentType("multipart/form-data"); //2.將數據轉爲xml格式的字符串 Element root = new Element("Demo-list"); Document document = new Document(root); for(Demo demo:list){ Element element = new Element("Demo"); element.addContent(new Element("demoId").setText(String.valueOf(demo.getDemoId()))); element.addContent(new Element("demoName").setText(demo.getDemoName())); root.addContent(element); } Format format = Format.getPrettyFormat(); //使xml文件 縮進效果 XMLOutputter xmlout = new XMLOutputter(format); String result = xmlout.outputString(document); System.out.println("轉爲xml格式的數據:"+result); try { //3.將內容轉爲byte[]格式 byte[] data = result.getBytes("UTF-8"); //4.將內容寫入響應流 OutputStream out = response.getOutputStream(); out.write(data); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } }
對於將實體類對象生成xml格式的字符串,這裏用到了jdom的工具包,故須要導入jdom-jar包。
sturts.xml配置:
<action name="createXML" class="FileAction" method="createXML"> </action>
好啦,完成了上面的步驟,xml文件的生成與下載就完成了,運行截圖:
附:
1.爲何大多數程序都要像下面的代碼這樣邊讀邊寫?
outputStream = new FileOutputStream(file);
byte[] temp = new byte[1024]; int size = -1; while ((size = inputStream.read(temp)) != -1) { // 每次讀取1KB,直至讀完 outputStream.write(temp, 0, size); }
爲了減小服務器的內存,因此咱們常常看見上面這段程序,此程序就是在邊讀邊寫(從一個文件中讀取內容,而後將內容寫到一個文件中),每次讀取1kb,每次寫1kb。