前言:
最近有給分配一個(gè)任務(wù)踢故,實(shí)現(xiàn)一個(gè)下載功能文黎,前提是當(dāng)在指定的目錄下去查找固定名字的文件,如果存在則直接讀取文件流在返回給瀏覽器殿较,如果沒有才去執(zhí)行數(shù)據(jù)庫去查耸峭,然后備份并輸出到瀏覽器進(jìn)行下載.
就這其中一個(gè)簡(jiǎn)單的功能,下面對(duì)這個(gè)部分進(jìn)行實(shí)現(xiàn)淋纲。
JSP頁面:
JSP代碼:
<c:if test="${page.list != null && fn:length(page.list) > 0}">
<c:forEach var="run" items="${page.list}" varStatus="st">
<tr>
<td style="text-align: center">${run.between}</td>
<td style="text-align: center">${run.typeNo}</td>
<td style="text-align: center">${run.status}</td>
<td style="text-align: center">${run.recall}</td>
<td style="text-align: center">${run.precision}</td>
<td style="text-align: center">${run.kind}</td>
<td class="td-manage" style="text-align: center">
<a title="下載" href="/CategoryTestRunData/downLoad?id=${run.id}">
<i class="layui-icon layui-icon-download-circle"></i>
</a>
</td>
</tr>
</c:forEach>
</c:if>
說明:<font color=red>在測(cè)試的時(shí)候發(fā)現(xiàn)下載這里如果寫Ajax異步請(qǐng)求下載話這個(gè)是無法請(qǐng)求的劳闹,所以這里寫直鏈。</font>
控制器:
控制層代碼:
/**
* Excel表下載導(dǎo)出
* @return
*/
@ResponseBody
@RequestMapping("/downLoad")
public void downLoad(String id, HttpServletResponse response, HttpServletRequest request) throws IOException {
log.info("Excel表下載導(dǎo)出洽瞬,傳入?yún)?shù):"+id);
//目標(biāo)路徑
String dist = "/data/download/";
//String dist = "F:/operate/download/";
File fileList = new File(dist);
if (!fileList.exists()){
fileList.mkdirs();
}
//判斷是否存在ID為名的文件
String[] list = fileList.list();
boolean isExist = true; //默認(rèn)該文件存在標(biāo)志
for (String name_id : list) {
String sub_name = StringUtils.substring(name_id,0,name_id.lastIndexOf("."));
if (StringUtils.equals(sub_name,id)){
//存在預(yù)下載文件
//獲取輸入流輸出到瀏覽器
FileInputStream fileInputStream = new FileInputStream(dist+name_id);
OutputStream outputStream = response.getOutputStream();
//設(shè)置Http響應(yīng)頭告訴瀏覽器下載這個(gè)附件,下載的文件名也是在這里設(shè)置的
//獲得瀏覽器代理信息
final String userAgent = request.getHeader("USER-AGENT");
//判斷瀏覽器代理并分別設(shè)置響應(yīng)給瀏覽器的編碼格式
String finalFileName = null;
if(StringUtils.contains(userAgent, "MSIE")||StringUtils.contains(userAgent,"Trident")){//IE瀏覽器
finalFileName = URLEncoder.encode(name_id,"UTF8");
System.out.println("IE瀏覽器");
}else if(StringUtils.contains(userAgent, "Mozilla")){//google,火狐瀏覽器
finalFileName = new String(name_id.getBytes(), "ISO8859-1");
}else{
finalFileName = URLEncoder.encode(name_id,"UTF8");//其他瀏覽器
}
//設(shè)置HTTP響應(yīng)頭
response.reset();//重置 響應(yīng)頭
response.setContentType("application/x-download");//告知瀏覽器下載文件本涕,而不是直接打開,瀏覽器默認(rèn)為打開
response.addHeader("Content-Disposition" ,"attachment;filename=" +finalFileName+ "");//下載文件的名稱
byte[] bytes = new byte[2048];
int len = 0;
while ((len = fileInputStream.read(bytes))>0){
outputStream.write(bytes,0,len);
}
fileInputStream.close();
outputStream.close();
return ;
}
}
isExist = false;
if (!isExist){
try{
//輸出寫入到服務(wù)器備份
ExcelWriter writer = ExcelUtil.getWriter(dist+id+".xlsx");
List<RecordDown> recordList = categoryTestRunDataService.getDownLoadList(Long.parseLong(id));
log.info("返回?cái)?shù)據(jù):"+JSON.toJSONString(recordList));
if (recordList.size() == 0){
}
writer.addHeaderAlias("mercNum","商戶編號(hào)");
writer.addHeaderAlias("triggerTime","風(fēng)險(xiǎn)類別觸發(fā)時(shí)間");
writer.addHeaderAlias("isRisk","是否風(fēng)險(xiǎn)商戶");
writer.addHeaderAlias("kind","對(duì)應(yīng)風(fēng)險(xiǎn)種類");
writer.addHeaderAlias("createHisTime","商戶入網(wǎng)時(shí)間");
writer.addHeaderAlias("region","商戶所屬地區(qū)");
for (int i = 0; i < 6; i++) {
writer.setColumnWidth(i,35);
}
// 一次性寫出內(nèi)容伙窃,使用默認(rèn)樣式菩颖,強(qiáng)制輸出標(biāo)題
writer.write(recordList, true);
// 關(guān)閉writer,釋放內(nèi)存
writer.close();
//寫入到瀏覽器
ExcelWriter writerToBrowser = ExcelUtil.getWriter(true);
writerToBrowser.write(recordList, true);
OutputStream outputStream = response.getOutputStream();
//獲得瀏覽器代理信息
final String userAgent = request.getHeader("USER-AGENT");
//判斷瀏覽器代理并分別設(shè)置響應(yīng)給瀏覽器的編碼格式
String finalFileName = null;
if(StringUtils.contains(userAgent, "MSIE")||StringUtils.contains(userAgent,"Trident")){//IE瀏覽器
finalFileName = URLEncoder.encode(id+".xlsx","UTF8");
System.out.println("IE瀏覽器");
}else if(StringUtils.contains(userAgent, "Mozilla")){//google,火狐瀏覽器
String fileName= id+".xlsx";
finalFileName = new String(fileName.getBytes(), "ISO8859-1");
}else{
finalFileName = URLEncoder.encode(id+".xlsx","UTF8");//其他瀏覽器
}
//設(shè)置HTTP響應(yīng)頭
response.reset();//重置 響應(yīng)頭
response.setContentType("application/x-download");//告知瀏覽器下載文件为障,而不是直接打開晦闰,瀏覽器默認(rèn)為打開
response.addHeader("Content-Disposition" ,"attachment;filename=" +finalFileName+ "");//下載文件的名稱
writerToBrowser.flush(outputStream, true);
writerToBrowser.close();
IoUtil.close(outputStream);
}catch (Exception e){
e.printStackTrace();
log.info("錯(cuò)誤信息:"+e);
}
}
}
說明:<font color=green>項(xiàng)目實(shí)現(xiàn)邏輯</font>
-
先去指定路徑查找,是否有指定目錄鳍怨,是否有以ID為名的文件呻右。
//目標(biāo)路徑 String dist = "/data/download/"; //String dist = "F:/operate/download/"; File fileList = new File(dist); if (!fileList.exists()){ fileList.mkdirs(); } //判斷是否存在ID為名的文件 String[] list = fileList.list(); boolean isExist = true; //默認(rèn)該文件存在標(biāo)志 for (String name_id : list) { String sub_name = StringUtils.substring(name_id,0,name_id.lastIndexOf(".")); //這里對(duì)循環(huán)拿到的文件名和目標(biāo)文件名匹配 if (StringUtils.equals(sub_name,id)){ //這里對(duì)匹配到的文件讀取并輸出到瀏覽器 } }
-
如果存在以ID為名的文件。
//存在預(yù)下載文件 //獲取輸入流輸出到瀏覽器 FileInputStream fileInputStream = new FileInputStream(dist+name_id); OutputStream outputStream = response.getOutputStream(); //設(shè)置Http響應(yīng)頭告訴瀏覽器下載這個(gè)附件,下載的文件名也是在這里設(shè)置的 //獲得瀏覽器代理信息 final String userAgent = request.getHeader("USER-AGENT"); //判斷瀏覽器代理并分別設(shè)置響應(yīng)給瀏覽器的編碼格式,部分瀏覽器編碼格式不同鞋喇,這里的操作防止下載是防止文件名亂碼 String finalFileName = null; if(StringUtils.contains(userAgent, "MSIE")||StringUtils.contains(userAgent,"Trident")){//IE瀏覽器 finalFileName = URLEncoder.encode(name_id,"UTF8"); System.out.println("IE瀏覽器"); }else if(StringUtils.contains(userAgent, "Mozilla")){//google,火狐瀏覽器 finalFileName = new String(name_id.getBytes(), "ISO8859-1"); }else{ finalFileName = URLEncoder.encode(name_id,"UTF8");//其他瀏覽器 } //設(shè)置HTTP響應(yīng)頭 response.reset();//重置 響應(yīng)頭 response.setContentType("application/x-download");//告知瀏覽器下載文件声滥,而不是直接打開,瀏覽器默認(rèn)為打開 response.addHeader("Content-Disposition" ,"attachment;filename=" +finalFileName);//下載文件的名稱 byte[] bytes = new byte[2048]; int len = 0; while ((len = fileInputStream.read(bytes))>0){ //寫入到輸出流 outputStream.write(bytes,0,len); } fileInputStream.close(); outputStream.close(); return ;
-
當(dāng)指定文件目錄沒有目標(biāo)文件名時(shí)去查詢相關(guān)數(shù)據(jù)确徙,進(jìn)行指定路徑備份醒串。
//輸出寫入到服務(wù)器備份 ExcelWriter writer = ExcelUtil.getWriter(dist+id+".xlsx"); //數(shù)據(jù)庫查詢結(jié)果 List<RecordDown> recordList = categoryTestRunDataService.getDownLoadList(Long.parseLong(id)); log.info("返回?cái)?shù)據(jù):"+JSON.toJSONString(recordList)); if (recordList.size() == 0){ //id下沒有數(shù)據(jù)集合 } //第一個(gè)參數(shù)是實(shí)體類屬性,第二個(gè)參數(shù)是Excel對(duì)應(yīng)的屬性注釋 writer.addHeaderAlias("me**Num","商**號(hào)"); writer.addHeaderAlias("tr**rTime","風(fēng)險(xiǎn)****時(shí)間"); writer.addHeaderAlias("is**sk","是否**商戶"); writer.addHeaderAlias("k**d","對(duì)應(yīng)**種類"); writer.addHeaderAlias("cre****sTime","商戶**時(shí)間"); writer.addHeaderAlias("re**on","商戶**地區(qū)"); //設(shè)置列的寬度 for (int i = 0; i < 6; i++) { writer.setColumnWidth(i,35); } // 一次性寫出內(nèi)容鄙皇,使用默認(rèn)樣式芜赌,強(qiáng)制輸出標(biāo)題 writer.write(recordList, true); // 關(guān)閉writer,釋放內(nèi)存 writer.close();
備份完成后再將輸出到瀏覽器伴逸,具體代碼和上方(2.如果存在以ID為名的文件缠沈。)的邏輯相同。這里不再贅述。
-
下載結(jié)果洲愤。
| 商號(hào) | 風(fēng)險(xiǎn)*時(shí)間 | 是否商戶 | 對(duì)應(yīng)種類 | 商戶時(shí)間 | 商戶*地區(qū) |
| ——: | ————————-: | ————: | ————: | ————————-: | ————: |
| 123 | 2020-04-10 11:31:32 | 是 | ** | 2020-04-10 11:31:32 | 商戶 |
補(bǔ)充:一般情況下颓芭,我們?cè)谶M(jìn)行下載功能的時(shí)候需要告訴瀏覽器他的類型。
response.setContentType("application/x-download")
是文件而不是頁面柬赐,設(shè)置瀏覽器自帶下載功能添加文件名亡问。
response.addHeader("Content-Disposition" ,"attachment;filename=" +finalFileName+ "")
實(shí)現(xiàn)方式:
實(shí)現(xiàn)瀏覽器下載可以有兩種方式:
方法一:
<action name="toauctionExcelAction"class="theauctionaction"method="Excel Theauctioninfo">
<result name="success"type="stream">
<param name="contentType">application/vnd.ms-excel;charset=UTF-8</param>
<param name="contentoisposition">attachment肛宋;filename="${auctionName}"</param>
<param name="inputName">excelTheauctioninfo</param>
</result>
</action>
? 從這個(gè)配置可以看出來這個(gè)是Struts2里面的寫法州藕,Struts2每一個(gè)方法都會(huì)有一個(gè)action作為配置信息,這樣子使得配置文件更為方法和繁瑣酝陈。
方法二:
//設(shè)置HTTP響應(yīng)頭
response.reset();//重置 響應(yīng)頭
response.setContentType("application/x-download");//告知瀏覽器下載文件床玻,而不是直接打開,瀏覽器默認(rèn)為打開
response.addHeader("Content-Disposition" ,"attachment;filename=" +finalFileName);//下載文件的名稱
? 直接在控制層中傳入?yún)?shù)HttpServletResponse response
利用response
設(shè)置頭信息和文件類型下載沉帮,這樣做的好處是只對(duì)這一個(gè)方法有效锈死,不會(huì)對(duì)其他請(qǐng)求造成影響。