您好,登錄后才能下訂單哦!
我們要將Web應用系統中的文件資源提供給用戶進行下載,首先我們要有一個頁面列出上傳文件目錄下的所有文件,當用戶點擊文件下載超鏈接時就進行下載操作,編寫一個ListFileServlet,用于列出Web應用系統中所有下載文件
獲取文件列表
package me.gacl.web.controller;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ListFileServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取上傳文件的目錄
String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//存儲要下載的文件名
Map<String,String> fileNameMap = new HashMap<String,String>();
//遞歸遍歷filepath目錄下的所有文件和目錄,將文件的文件名存儲到map集合中
listfile(new File(uploadFilePath),fileNameMap);//File既可以代表一個文件也可以代表一個目錄
//將Map集合發送到listfile.jsp頁面進行顯示
request.setAttribute("fileNameMap", fileNameMap);
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
}
public void listfile(File file,Map<String,String> map){
//如果file代表的不是一個文件,而是一個目錄
if(!file.isFile()){
//列出該目錄下的所有文件和目錄
File files[] = file.listFiles();
//遍歷files[]數組
for(File f : files){
//遞歸
listfile(f,map);
}
}else{
/**
處理文件名,上傳后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid部分
file.getName().indexOf("")檢索字符串中第一次出現"_"字符的位置,如果文件名類似于:9349249849-88343-8344_阿_凡達.avi
那么file.getName().substring(file.getName().indexOf("")+1)處理之后就可以得到阿_凡達.avi部分
*/
String realName = file.getName().substring(file.getName().indexOf("")+1);
//file.getName()得到的是文件的原始名稱,這個名稱是唯一的,因此可以作為key,realName是處理過后的名稱,有可能會重復
map.put(file.getName(), realName);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ListFileServlet中listfile方法,listfile方法是用來列出目錄下的所有文件的,listfile方法內部用到了遞歸,在實際開發當中,我們肯定會在數據庫創建一張表,里面會存儲上傳的文件名以及文件的具體存放目錄,我們通過查詢表就可以知道文件AxiTrader代理申請www.fx61.com/brokerlist/axitrader.html的具體存放目錄,是不需要用到遞歸操作的,這個例子是因為沒有使用數據庫存儲上傳的文件名和文件的具體存放位置,而上傳文件的存放位置又使用了散列算法打散存放,所以需要用到遞歸,在遞歸時,將獲取到的文件名存放到從外面傳遞到listfile方法里面的Map集合當中,這樣就可以保證所有的文件都存放在同一個Map集合當中。
配置
在Web.xml文件中配置ListFileServlet
<servlet>
<servlet-name>ListFileServlet</servlet-name>
<servlet-class>me.gacl.web.controller.ListFileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ListFileServlet</servlet-name>
<url-pattern>/servlet/ListFileServlet</url-pattern>
</servlet-mapping>
下載頁面
展示下載文件的listfile.jsp頁面如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML>
<html>
<head>
<title>下載文件顯示頁面</title>
</head>
<body>
<!-- 遍歷Map集合 -->
<c:forEach var="me" items="${fileNameMap}">
<c:url value="/servlet/DownLoadServlet" var="downurl">
<c:param name="filename" value="${me.key}"></c:param>
</c:url>
${me.value}<a href="${downurl}">下載</a>
<br/>
</c:forEach>
</body>
</html>
實現文件下載
編寫一個用于處理文件下載的Servlet,DownLoadServlet的代碼如下:
public class DownLoadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到要下載的文件名
String fileName = request.getParameter("filename"); //23239283-92489-阿凡達.avi
//上傳的文件都是保存在/WEB-INF/upload目錄下的子目錄當中
String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
//通過文件名找出文件的所在目錄
String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
//得到要下載的文件
File file = new File(path + "\" + fileName);
//如果文件不存在
if(!file.exists()){
request.setAttribute("message", "您要下載的資源已被刪除!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//處理文件名
String realname = fileName.substring(fileName.indexOf("_")+1);
//設置響應頭,控制瀏覽器下載該文件
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
//讀取要下載的文件,保存到文件輸入流
FileInputStream in = new FileInputStream(path + "\" + fileName);
//創建輸出流
OutputStream out = response.getOutputStream();
//創建緩沖區
byte buffer[] = new byte[1024];
int len = 0;
//循環將輸入流中的內容讀取到緩沖區當中
while((len=in.read(buffer))>0){
//輸出緩沖區的內容到瀏覽器,實現文件下載
out.write(buffer, 0, len);
}
//關閉文件輸入流
in.close();
//關閉輸出流
out.close();
}
public String findFileSavePathByFileName(String filename,String saveRootPath){
int hashcode = filename.hashCode();
int dir1 = hashcode&0xf; //0--15
int dir2 = (hashcode&0xf0)>>4; //0-15
String dir = saveRootPath + "\" + dir1 + "\" + dir2; //upload\2\3 upload\3\5
File file = new File(dir);
if(!file.exists()){
//創建目錄
file.mkdirs();
}
return dir;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
配置
<servlet>
<servlet-name>DownLoadServlet</servlet-name>
<servlet-class>me.gacl.web.controller.DownLoadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownLoadServlet</servlet-name>
<url-pattern>/servlet/DownLoadServlet</url-pattern>
</servlet-mapping>
1.html5支持的文件下載
非常簡單代碼如下:
<a download="下載文件.txt">下載文件</a>
這種方式不支持ie瀏覽器
2.需要后臺支持的文件下載:
前端代碼如下:
function getRootPath() {
//獲取當前網址,如: http://localhost:8083/uimcardprj/share/meun.jsp
var curWwwPath = window.document.location.href;
//獲取主機地址之后的目錄,如: uimcardprj/share/meun.jsp
var pathName = window.document.location.pathname;
var pos = curWwwPath.indexOf(pathName);
//獲取主機地址,如: http://localhost:8083
var localhostPaht = curWwwPath.substring(0, pos);
//獲取帶"/"的項目名,如:/uimcardprj
var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
return (localhostPaht + projectName);
}
function downloadExcel(fileName) {
fileName = encodeURI(fileName);
var url = getRootPath() + "/static/excel/" + fileName;
window.location.href = "data/downloadexcel?fileName=" + fileName + "&url=" + url;
}
此處需要傳遞下載文件的文件名稱與文件的地址(為了避免服務器路徑問題,此處直接使用前端傳遞的url路徑地址,這種方式也可以用來下載第三方網站上的文件資源),注意對于文件名稱需要處理文件名稱中的中文字符與特殊字符需要使用js方法encodeURI對文件名稱編碼
后臺代碼:
/**
/**
@Description: ie, chrom, firfox下處理文件名顯示亂碼
*/
public static String processFileName(HttpServletRequest request,
String fileNames) {
String codedfilename = null;
try {
String agent = request.getHeader("USER-AGENT");
if (null != agent && agent.indexOf("MSIE") > -1 || null != agent
&& agent.indexOf("Trident") > -1) {// ie
String name = java.net.URLEncoder.encode(fileNames, "UTF8").replaceAll("\+","%20");
codedfilename = name;
} else {// 火狐,chrome等
codedfilename = new String(fileNames.getBytes("UTF-8"),
"iso-8859-1");
}
} catch (Exception e) {
logger.error("文件名稱編碼出錯", e);
}
return codedfilename;
}
下載文件代碼需要注意的地方就只有文件名稱的編碼問題,其他代碼很簡單,需要特別注意URLEncoder.encode將空格轉換為+,需要特殊處理轉換為%20
3.下載后臺實時生成的文件
簡單的后臺實時生成文件基本代碼和步驟二一致,只是將從網絡獲取的文件改為從本機獲取就行了
4.使用post方法下載文件
post方法下載文件主要可以通過兩種方式解決
第一種將post提交到當前頁面的隱藏iframe即可,但這種方式在ie和chmore中會有兩種表現形式(一種直接在當前頁面下載,一種會打開一個空白頁下載)
var downLoadFile = function (options) {
var config = $.extend(true, {method: 'post'}, options);
var $iframe = $('<iframe id="down-file-iframe" />');
var $form = $('<form target="down-file-iframe" method="' + config.method + '" />');
$form.attr('action', config.url);
for (var key in config.data) {
var input = $("<input hidden>");
input.attr("name", key);
input.val(config.data[key]);
$form.append(input);
}
$iframe.append($form);
$(document.body).append($iframe);
$form[0].submit();
$iframe.remove();
}
//調用方法
downLoadFile({
url: '...', //請求的url
data: {
name:"",
size:"",
......
}//要發送的數據
});
使用以上方式即可使用post的方法下載文件
第二種方法很簡單,可以先用post方式上傳參數,將參數以緩存的形式存儲在服務端并返回key給前端,再在post的回調方法中使用get方式傳遞key給后臺下載文件
樣例代碼很簡單,如下:
$.post("download",params, function (data) {
if (data.success) {
window.location.href = "download?generatorId=" + data.data;
} else {
alert(data.msg);
}
})
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。