寫一個Apache文件上傳與文件下載的案例:以供今后學習
web.xml配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<span style= "font-family:SimSun;font-size:14px;" ><?xml version= "1.0" encoding= "UTF-8" ?> <web-app xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns= "http://java.sun.com/xml/ns/javaee" xsi:schemaLocation= "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version= "2.5" > <display-name>FileUploadAndDownload< /display-name > <welcome- file -list> <welcome- file >index.html< /welcome-file > <welcome- file >index.htm< /welcome-file > <welcome- file >index.jsp< /welcome-file > <welcome- file >default.html< /welcome-file > <welcome- file >default.htm< /welcome-file > <welcome- file >default.jsp< /welcome-file > < /welcome-file-list > <!-- 上傳配置 --> <servlet> <servlet-name>uploadHandleServlet< /servlet-name > <servlet-class>com.zeng.controller.UploadHandleServlet< /servlet-class > < /servlet > <servlet-mapping> <servlet-name>uploadHandleServlet< /servlet-name > <url-pattern> /upload/uploadHandleServlet < /url-pattern > < /servlet-mapping > <servlet> <servlet-name>listFileServlet< /servlet-name > <servlet-class>com.zeng.controller.ListFileServlet< /servlet-class > < /servlet > <servlet-mapping> <servlet-name>listFileServlet< /servlet-name > <url-pattern> /listFileServlet < /url-pattern > < /servlet-mapping > <servlet> <servlet-name>downLoadServlet< /servlet-name > <servlet-class>com.zeng.controller.DownLoadServlet< /servlet-class > < /servlet > <servlet-mapping> <servlet-name>downLoadServlet< /servlet-name > <url-pattern> /download/downLoadServlet < /url-pattern > < /servlet-mapping > < /web-app >< /span > |
2.upload.jsp文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<span style= "font-family:SimSun;font-size:14px;" ><%@page language= "java" pageEncoding= "UTF-8" %> <!DOCTYPE HTML> <html> < head > <title>文件上傳< /title > < /head > <body> <!-- ${pageContext.request.contextPath} : 作用是取出部署的應用程序名 缺點:操作不便,其他工具無法正確解釋${pageContext.request.contextPath} 如果Servlet的配置路徑為 /upload/uploadHandleServlet action跳轉路徑為: ${pageContext.request.contextPath} /upload/uploadHandleServlet 上傳文件時,必須 1.enctype= "multipart/form-data" 2.method=post --> <form action= "${pageContext.request.contextPath}/upload/uploadHandleServlet" enctype= "multipart/form-data" method= "post" > 上傳用戶:<input type = "text" name= "username" ><br/> 上傳文件1:<input type = "file" name= "file1" ><br/> 上傳文件2:<input type = "file" name= "file2" ><br/> <input type = "submit" value= "提交" > < /form > < /body > < /html >< /span > |
3.message.jsp
1
2
3
4
5
6
7
8
9
10
|
<span style= "font-family:SimSun;font-size:14px;" ><%@page language= "java" pageEncoding= "UTF-8" %> <!DOCTYPE HTML> <html> < head > <title>消息提示< /title > < /head > <body> ${message} < /body > < /html >< /span > |
4.UploadHandleServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
|
<span style= "font-family:SimSun;font-size:14px;" >package com.zeng.controller; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; /** * @ClassName: UploadHandleServlet * @Description: TODO(這里用一句話描述這個類的作用) */ public class UploadHandleServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 得到上傳文件的保存目錄,將上傳的文件存放于WEB-INF目錄下,不允許外界直接訪問,保證上傳文件的安全 String savePath = this.getServletContext().getRealPath( "/WEB-INF/upload" ); // 上傳時生成的臨時文件保存目錄 String tempPath = this.getServletContext().getRealPath( "/WEB-INF/temp" ); File tmpFile = new File(tempPath); if (!tmpFile.exists()) { // 創建臨時目錄 tmpFile. mkdir (); } // 消息提示 String message = "" ; try{ // 使用Apache文件上傳組件處理文件上傳步驟: //1 、創建一個DiskFileItemFactory工廠 DiskFileItemFactory factory = new DiskFileItemFactory(); // 設置工廠的緩沖區的大小,當上傳的文件大小超過緩沖區的大小時,就會生成一個臨時文件存放到指定的臨時目錄當中。 factory.setSizeThreshold(1024*100); // 設置緩沖區的大小為100KB,如果不指定,那么緩沖區的大小默認是10KB // 設置上傳時生成的臨時文件的保存目錄 factory.setRepository(tmpFile); //2 、創建一個文件上傳解析器 ServletFileUpload upload = new ServletFileUpload(factory); // 監聽文件上傳進度 upload.setProgressListener(new ProgressListener(){ public void update(long pBytesRead, long pContentLength, int arg2) { System.out.println( "文件大小為:" + pContentLength + ",當前已處理:" + pBytesRead + ",arg2: " + arg2); /** * 文件大小為:14608,當前已處理:4096 文件大小為:14608,當前已處理:7367 文件大小為:14608,當前已處理:11419 文件大小為:14608,當前已處理:14608 */ } }); // 解決上傳文件名的中文亂碼 upload.setHeaderEncoding( "UTF-8" ); //3 、判斷提交上來的數據是否是上傳表單的數據 if (!ServletFileUpload.isMultipartContent(request)){ // 按照傳統方式獲取數據 return ; } // 設置上傳單個文件的大小的最大值,目前是設置為1024*1024*20字節,也就是20MB upload.setFileSizeMax(1024*1024*20); // 設置上傳文件總量的最大值,最大值=同時上傳的多個文件的大小的最大值的和,目前設置為100MB upload.setSizeMax(1024*1024*100); //4 、使用ServletFileUpload解析器解析上傳數據,解析結果返回的是一個List<FileItem>集合,每一個FileItem對應一個Form表單的輸入項 List<FileItem> list = upload.parseRequest(request); for (FileItem item : list){ // 如果fileitem中封裝的是普通輸入項的數據 if (item.isFormField()){ String name = item.getFieldName(); // 解決普通輸入項的數據的中文亂碼問題 String value = item.getString( "UTF-8" ); System.out.println(name + "=" + value); } else { // 如果fileitem中封裝的是上傳文件 // 得到上傳的文件名稱, String filename = item.getName(); System.out.println(filename); if (filename==null || filename.trim().equals( "" )){ continue ; } // 注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt // 處理獲取到的上傳文件的文件名的路徑部分,只保留文件名部分 filename = filename.substring(filename.lastIndexOf( "\\" )+1); // 得到上傳文件的擴展名 String fileExtName = filename.substring(filename.lastIndexOf( "." )+1); // 如果需要限制上傳的文件類型,那么可以通過文件的擴展名來判斷上傳的文件類型是否合法 System.out.println( "上傳的文件的擴展名是:" +fileExtName); // 獲取item中的上傳文件的輸入流 InputStream in = item.getInputStream(); // 得到文件保存的名稱 String saveFilename = makeFileName(filename); // 文件名:d507ef2e-aca9-4908-a8b9-c1d1c6a2f4d9_日語二級語法大全(推薦).doc //System .out.println( "saveFilename: " + saveFilename); // 得到文件的保存目錄 String realSavePath = makePath(saveFilename, savePath); // 創建一個文件輸出流 FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename); // 創建一個緩沖區 byte buffer[] = new byte[1024]; // 判斷輸入流中的數據是否已經讀完的標識 int len = 0; // 循環將輸入流讀入到緩沖區當中,(len= in . read (buffer))>0就表示 in 里面還有數據 while ((len= in . read (buffer))>0){ // 使用FileOutputStream輸出流將緩沖區的數據寫入到指定的目錄(savePath + "\\" + filename)當中 out.write(buffer, 0, len); } // 關閉輸入流 in .close(); // 關閉輸出流 out.close(); // 刪除處理文件上傳時生成的臨時文件 //item .delete(); message = "文件上傳成功!" ; } } }catch (FileUploadBase.FileSizeLimitExceededException e) { e.printStackTrace(); request.setAttribute( "message" , "單個文件超出最大值!!!" ); request.getRequestDispatcher( "../message.jsp" ).forward(request, response); return ; }catch (FileUploadBase.SizeLimitExceededException e) { e.printStackTrace(); request.setAttribute( "message" , "上傳文件的總的大小超出限制的最大值!!!" ); request.getRequestDispatcher( "../message.jsp" ).forward(request, response); return ; }catch (Exception e) { message= "文件上傳失敗!" ; e.printStackTrace(); } request.setAttribute( "message" ,message); // 訪問路徑 /FileUploadAndDownload/upload/upload .jsp // 跳轉路徑 /FileUploadAndDownload/upload/listFileServlet // 轉發路徑 /FileUploadAndDownload/message .jsp // 當前路徑是在 /FileUploadAndDownload/upload/ 下,要跳到 /FileUploadAndDownload/ 下,必須.. /message .jsp //----- 如果 message.jsp是在 /FileUploadAndDownload/upload/ 下,則直接使用message.jsp request.getRequestDispatcher( "../message.jsp" ).forward(request, response); } /** * @Method: makeFileName * @Description: 生成上傳文件的文件名,文件名以:uuid+ "_" +文件的原始名稱 * @param filename 文件的原始名稱 * @ return uuid+ "_" +文件的原始名稱 */ private String makeFileName(String filename){ //2 .jpg // 為防止文件覆蓋的現象發生,要為上傳文件產生一個唯一的文件名 return UUID.randomUUID().toString() + "_" + filename; } /** * 為防止一個目錄下面出現太多文件,要使用 hash 算法打散存儲 * @Method: makePath * @param filename 文件名,要根據文件名生成存儲目錄 * @param savePath 文件存儲路徑 * @ return 新的存儲目錄 */ private String makePath(String filename,String savePath){ // 得到文件名的hashCode的值,得到的就是filename這個字符串對象在內存中的地址 int hashcode = filename.hashCode(); int dir1 = hashcode&0xf; //0--15 int dir2 = (hashcode&0xf0)>>4; //0-15 // 構造新的保存目錄 String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload \2\3 upload\3\5 //hashcode : -1390239557 dir1: 11 dir : 11 (以d507ef2e-aca9-4908-a8b9-c1d1c6a2f4d9_日語二級語法大全(推薦).doc為例子) System.out.println( "上傳前:hashcode: " + hashcode + " dir1: " +dir1 + " dir: " + dir2); //File 既可以代表文件也可以代表目錄 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); } } // ----------------------------------------------------------簡單版本,不處理上傳空間和上傳的文件名 // //import java.io.File; //import java.io.FileOutputStream; //import java.io.IOException; //import java.io.InputStream; //import java.util.List; //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; //import javax.servlet.http.HttpServletRequest; //import javax.servlet.http.HttpServletResponse; //import org.apache.commons.fileupload.FileItem; //import org.apache.commons.fileupload.disk.DiskFileItemFactory; //import org.apache.commons.fileupload.servlet.ServletFileUpload; // //public class UploadHandleServlet extends HttpServlet { // // public void doGet(HttpServletRequest request, HttpServletResponse response) // throws ServletException, IOException { // // 得到上傳文件的保存目錄,將上傳的文件存放于WEB-INF目錄下,不允許外界直接訪問,保證上傳文件的安全 // String savePath = this.getServletContext().getRealPath( "/WEB-INF/upload" ); // File file = new File(savePath); // // 判斷上傳文件的保存目錄是否存在 // if (! file .exists() && ! file .isDirectory()) { // System.out.println(savePath+ "目錄不存在,需要創建" ); // // 創建目錄 // file . mkdir (); // } // // 消息提示 // String message = "" ; // try{ // // 使用Apache文件上傳組件處理文件上傳步驟: // //1 、創建一個DiskFileItemFactory工廠 // DiskFileItemFactory factory = new DiskFileItemFactory(); // //2 、創建一個文件上傳解析器 // ServletFileUpload upload = new ServletFileUpload(factory); // // 解決上傳文件名的中文亂碼 // upload.setHeaderEncoding( "UTF-8" ); // //3 、判斷提交上來的數據是否是上傳表單的數據 // if (!ServletFileUpload.isMultipartContent(request)){ // // 按照傳統方式獲取數據 // return ; // } // //4 、使用ServletFileUpload解析器解析上傳數據,解析結果返回的是一個List<FileItem>集合,每一個FileItem對應一個Form表單的輸入項 // List<FileItem> list = upload.parseRequest(request); // for (FileItem item : list){ // // 如果fileitem中封裝的是普通輸入項的數據 // if (item.isFormField()){ // String name = item.getFieldName(); // // 解決普通輸入項的數據的中文亂碼問題 // String value = item.getString( "UTF-8" ); // //value = new String(value.getBytes( "iso8859-1" ), "UTF-8" ); // System.out.println(name + "=" + value); // } else { // 如果fileitem中封裝的是上傳文件 // // 得到上傳的文件名稱, // String filename = item.getName(); // System.out.println(filename); // if (filename==null || filename.trim().equals( "" )){ // continue ; // } // // 注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt // // 處理獲取到的上傳文件的文件名的路徑部分,只保留文件名部分 // filename = filename.substring(filename.lastIndexOf( "\\" )+1); // // 獲取item中的上傳文件的輸入流 // InputStream in = item.getInputStream(); // // 創建一個文件輸出流 // FileOutputStream out = new FileOutputStream(savePath + "\\" + filename); // // 創建一個緩沖區 // byte buffer[] = new byte[1024]; // // 判斷輸入流中的數據是否已經讀完的標識 // int len = 0; // // 循環將輸入流讀入到緩沖區當中,(len= in . read (buffer))>0就表示 in 里面還有數據 // while ((len= in . read (buffer))>0){ // // 使用FileOutputStream輸出流將緩沖區的數據寫入到指定的目錄(savePath + "\\" + filename)當中 // out.write(buffer, 0, len); // } // // 關閉輸入流 // in .close(); // // 關閉輸出流 // out.close(); // // 刪除處理文件上傳時生成的臨時文件 // item.delete(); // message = "文件上傳成功!" ; // } // } // }catch (Exception e) { // message= "文件上傳失敗!" ; // e.printStackTrace(); // // } // request.setAttribute( "message" ,message); // request.getRequestDispatcher( "/message.jsp" ).forward(request, response); // } // // public void doPost(HttpServletRequest request, HttpServletResponse response) // throws ServletException, IOException { // // doGet(request, response); // } // }< /span > <上傳文件完畢> |
1.listfile.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<span style= "font-family:SimSun;font-size:14px;" ><%@ 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 > <meta charset= "UTF-8" > <style type = "text/css" > .filelistTab{ width: 500px; border: 2px solid gray; border-collapse: collapse; } .filelistTd{ height:25px; border: 1px solid gray; } < /style > < /head > <body> <%-- <c:url var= "path" value= "download/downLoadServlet" > <c:param name= "filename" value= "myOPQ" >< /c :param> < /c :url> <a href= "${path }" rel= "external nofollow" rel= "external nofollow" >下載文件< /a > --%> <!-- 遍歷Map集合 --> <table class= "filelistTab" > <c:forEach items= "${fileNameMap }" var= "fileNames" > < tr > <td class= "filelistTd" > <c:url value= "download/downLoadServlet" var= "path" > <c:param name= "filename" value= "${fileNames.key}" >< /c :param> < /c :url>${fileNames.value} < /td > <td class= "filelistTd" ><a href= "${path }" rel= "external nofollow" rel= "external nofollow" >下載< /a >< /td > < /tr > < /c :forEach> < /table > < /body > < /html >< /span > |
2.ListFileServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
<span style= "font-family:SimSun;font-size:14px;" >package com.zeng.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; /** * @ClassName: ListFileServlet * @Description: 列出Web系統中所有下載文件 */ public class ListFileServlet extends HttpServlet { /* * ListFileServlet中listfile方法,listfile方法是用來列出目錄下的所有文件的, * listfile方法內部用到了遞歸,在實際開發當中,我們肯定會在數據庫創建一張表, * 里面會存儲上傳的文件名以及文件的具體存放目錄,我們通過查詢表就可以知道文件的具體存放目錄, * 是不需要用到遞歸操作的,這個例子是因為沒有使用數據庫存儲上傳的文件名和文件的具體存放位置, * 而上傳文件的存放位置又使用了散列算法打散存放,所以需要用到遞歸,在遞歸時, * 將獲取到的文件名存放到從外面傳遞到listfile方法里面的Map集合當中, * 這樣就可以保證所有的文件都存放在同一個Map集合當中。 * */ 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>(); // File file = new File(uploadFilePath); if (! file .exists()){ // 如果文件路徑不存在,則轉發 request.setAttribute( "message" , "路徑為空路徑" ); request.getRequestDispatcher( "message.jsp" ).forward(request, response); } else { // 如果文件路徑存在,則進行遍歷所有文件 // 遞歸遍歷filepath目錄下的所有文件和目錄,將文件的文件名存儲到map集合中 listfile( file ,fileNameMap); //File 既可以代表一個文件也可以代表一個目錄 // 將Map集合發送到listfile.jsp頁面進行顯示 request.setAttribute( "fileNameMap" , fileNameMap); request.getRequestDispatcher( "listfile.jsp" ).forward(request, response); } } /** * @Method: listfile * @Description: 遞歸遍歷指定目錄下的所有文件 * @param file 即代表一個文件,也代表一個文件目錄 * @param map 存儲文件名的Map集合 */ 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); } }< /span > |
<展示完畢>
1.DownLoadServlet.Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
<span style= "font-family:SimSun;font-size:14px;" >package com.zeng.controller; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DownLoadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println( "進入" ); /* * fileName的格式:文件名以:uuid+ "_" +文件的原始名稱 * 得到fileName:d507ef2e-aca9-4908-a8b9-c1d1c6a2f4d9_日語二級語法大全(推薦).doc * * listfile.jsp的路徑傳遞是以 download /downLoadServlet 提交 * * 路徑內容為: * /FileUploadAndDownload/download/downLoadServlet * ?filename=d507ef2e-aca9-4908-a8b9-c1d1c6a2f4d9_日語二級語法大全(推薦).doc * */ String fileName = request.getParameter( "filename" ); // 注意:使用了下面一句字符轉碼時,出錯:打不到文件, //dir1 和dir2的數字前后各不相同,導致重新創建了文件,而文件內又沒有文件,故報找不到文件錯誤 //fileName = new String(fileName.getBytes( "iso8859-1" ), "UTF-8" ); System.out.println( "fileName: " + fileName); // 上傳的文件都是保存在 /WEB-INF/upload 目錄下的子目錄當中 String fileSaveRootPath=this.getServletContext().getRealPath( "/WEB-INF/upload" ); System.out.println( "fileSaveRootPath: " + fileSaveRootPath); // 通過文件名找出文件的所在目錄 String path = findFileSavePathByFileName(fileName,fileSaveRootPath); System.out.println( "path: " + path); // 服務器安裝位置\wtpwebapps\FileUploadAndDownload\WEB-INF\ upload\11\11 // 得到要下載的文件,文件類型是 : uuid + "_" + 文件名 File file = new File(path + "\\" + fileName); System.out.println( "file: " + file .getAbsolutePath()); // 如果文件不存在 if (! file .exists()){ request.setAttribute( "message" , "您要下載的資源已被刪除!!" ); // 轉發到錯誤頁面,此處要注意路徑問題 request.getRequestDispatcher( "../message.jsp" ).forward(request, response); return ; } // 處理文件名,得到去除uuid后的文件名 String realname = fileName.substring(fileName.indexOf( "_" )+1); System.out.println( "realname: " + realname); /* * 文件下載 * 設置content-disposition響應頭控制瀏覽器以下載的形式打開文件 * 下載中文文件時,需要注意的地方就是中文文件名要使用 * URLEncoder.encode()方法進行編碼(URLEncoder.encode(fileName, "字符編碼" )), * 否則會出現文件名亂碼。 * */ response.setHeader( "content-disposition" , "attachment;filename=" + URLEncoder.encode(realname, "UTF-8" )); // 讀取要下載的文件,保存到文件輸入流,此處的路徑還是帶有uuid 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(); } /** * @Method: findFileSavePathByFileName * @Description: 通過文件名和存儲上傳文件根目錄找出要下載的文件的所在路徑 * @param filename 要下載的文件名 * @param saveRootPath 上傳文件保存的根目錄,也就是 /WEB-INF/upload 目錄 * @ return 要下載的文件的存儲目錄 */ 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 //hashcode : -1390239557 dir1: 11 dir : 11 (以d507ef2e-aca9-4908-a8b9-c1d1c6a2f4d9_日語二級語法大全(推薦).doc為例子) System.out.println( "hashcode: " + hashcode + " dir1: " +dir1 + " dir: " + dir2); 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); } }< /span > |
以上所述是小編給大家介紹的Apache 文件上傳與文件下載案例詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://blog.csdn.net/zzjvslove/article/details/74209986