servlet實(shí)現(xiàn)文件上傳與下載功能
本文實(shí)例為大家分享了servlet實(shí)現(xiàn)文件上傳與下載的具體代碼,供大家參考,具體內(nèi)容如下
內(nèi)容
我們分兩大模塊來(lái)進(jìn)行講解,即上傳的實(shí)現(xiàn),與下載的實(shí)現(xiàn)
上傳的實(shí)現(xiàn)
注意了我們?cè)趯?xiě)上傳表單的時(shí)候必須聲明提交方式為post類(lèi)型,enctype="multipart/form-data",這樣的話(huà)才能實(shí)現(xiàn)上傳。
當(dāng)我們提交表單的時(shí)候看看響應(yīng)體中都有什么內(nèi)容:
好了,我們有了數(shù)據(jù)了,接下來(lái)我們?cè)趺刺崛?shù)據(jù)呢,注意我們已經(jīng)不能使用requeest.getParamter()方法來(lái)進(jìn)行參數(shù)的提取了,那怎么辦呢,我們總不能自己寫(xiě)實(shí)現(xiàn)類(lèi)來(lái)進(jìn)行分割吧!我們可以使用Commons提供的小工具。
好了,讓我們來(lái)看看具體的操作步驟吧!這里我就不詳細(xì)說(shuō)了,一文代碼流過(guò):
/** * 需要解決的問(wèn)題: * 1 必須要把文件存放到WEB-INF目錄下,避免用戶(hù)看到 * 2 文件名相關(guān)問(wèn)題 * 1 有的瀏覽器會(huì)傳遞絕對(duì)路徑到name中,我們只需要進(jìn)行拆分即可 * 2文件重名問(wèn)題,我們可以使用uuid * 3文件名亂碼問(wèn)題,我們已經(jīng)解決了。即request.setCharacterEncoding("utf-8"); * 3 文件打散問(wèn)題 * 1通過(guò)首字符打散 * 2通過(guò)時(shí)間打散 * 3通過(guò)hash打散 * 4上傳文件大小限制 * 1單個(gè)文件上傳大小限制 * 2總文件上傳大小限制 * 設(shè)置這兩個(gè)參數(shù)時(shí),我們必須在沒(méi)有解析之前執(zhí)行。 * 5 緩存大小與臨時(shí)目錄 * * * **/ public class FileUploadServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); /** * 我們使用commmons的小工具來(lái)進(jìn)行編碼 * 設(shè)置jsp頁(yè)面的enctype= “multipart/form-data“; * 1 創(chuàng)建FileItem工廠 * 2創(chuàng)建ServletFileUpload對(duì)象 * 3 解析request得到FileItem * 4對(duì)FileItem進(jìn)行操作 **/ String path = request.getSession().getServletContext().getRealPath("/WEB-INF"); //解決緩存大小,要不然你的內(nèi)存會(huì)爆的。 DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(1024 * 10,new File(path + "/" + "tmp2") ); ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory); List<FileItem> l = null; try { l = fileUpload.parseRequest(request); FileItem f2 = l.get(0); //解決文件存放在WEN_INF目錄下問(wèn)題 path = path + "/tmp"; //解決瀏覽器傳遞絕對(duì)路徑問(wèn)題 String name = f2.getName(); int i = name.lastIndexOf("/"); if(i != -1) { name = name.substring(i); } //解決文件重名問(wèn)題 name = (UUID.randomUUID().toString().replace("-","").trim()) + name; //文件打散問(wèn)題解決方法演示之hash打散 int has = name.hashCode(); //轉(zhuǎn)換位16進(jìn)制位,我們使用前兩個(gè)值來(lái)判斷 String hex = Integer.toHexString(has); path = path + "/" + hex.charAt(0) + "/" + hex.charAt(2) ; File file = new File(path); if(! file.exists()) { file.mkdirs(); } f2.write(new File(path + "/" + name)); request.setAttribute("msg","恭喜你,上傳成功了!"); request.getRequestDispatcher("/index.jsp").forward(request, response); } catch (Exception e) { request.setAttribute("msg",e.getMessage()); request.getRequestDispatcher("/index.jsp").forward(request, response); } } }
好了,上傳的問(wèn)題基本就解決了。
下載的實(shí)現(xiàn)
下面我們來(lái)看一下下載問(wèn)題的解決方案
下載文件是我們必須來(lái)設(shè)置兩個(gè)響應(yīng)頭,設(shè)置Content-Disposition:它的默認(rèn)值為inline,表示在瀏覽器窗口中打開(kāi)!attachment;filename=xxx要不然我們輸出的內(nèi)容不會(huì)彈出保存框,只會(huì)顯示在瀏覽器中。
設(shè)置Content-Type:你傳遞給客戶(hù)端的文件是什么MIME類(lèi)型
然后我們就可以new一個(gè)輸入流來(lái)讀取本地硬盤(pán)中的文件,在輸出到ServleoutputStream中
在來(lái)一行代碼流過(guò):
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * 設(shè)置兩個(gè)響應(yīng)頭 * 1Content-Type:你傳遞給客戶(hù)端的文件是什么MIME類(lèi)型 * 2Content-Disposition:它的默認(rèn)值為inline,表示在瀏覽器窗口中打開(kāi)!attachment;filename=xxx * * 需要解決的的問(wèn)題: * 1 下載文件名中文亂碼問(wèn)題 * 解決方法: * 針對(duì)不同的瀏覽器使用不同的編碼方式 火狐瀏覽器使用的是Base64編碼,其他瀏覽器一般都是使用url編碼 **/ String mimeType = request.getSession().getServletContext().getMimeType("\\WEB-INF\\tmp\\2\\5\\" + "87bd61a4b7c346a5a2e6c072de84acda5.JdbcUtils處理多線程并發(fā)訪問(wèn)問(wèn)題.avi"); //解決文件名亂碼問(wèn)題 String filename = "87bd61a4b7c346a5a2e6c072de84acda5.JdbcUtils處理多線程并發(fā)訪問(wèn)問(wèn)題.avi"; filename = encoding(filename, request); //兩個(gè)請(qǐng)求頭 response.setHeader("Content-Type",mimeType); response.setHeader("Content-Disposition","attachment;filename=" + filename); ServletOutputStream out = response.getOutputStream(); String path = request.getSession().getServletContext().getRealPath("\\WEB-INF\\tmp\\2\\5\\" + "87bd61a4b7c346a5a2e6c072de84acda5.JdbcUtils處理多線程并發(fā)訪問(wèn)問(wèn)題.avi"); File file = new File(path); FileInputStream inputStream = new FileInputStream(file); IOUtils.copy(inputStream, out, 1024*1024); } private String encoding(String filename,HttpServletRequest req) throws UnsupportedEncodingException { String user_agent = req.getHeader("User-Agent"); String encodingFileName = null; if(user_agent.contains("Firefox")) { //按道理來(lái)說(shuō)應(yīng)該使用 BASE64Encoder進(jìn)行編碼,但是不知道為什么不能成功 /*BASE64Encoder base64Encoder = new BASE64Encoder(); encodingFileName = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";*/ //那我們只能使用這種方式了 encodingFileName = new String(filename.getBytes("UTF-8"), "ISO-8859-1"); } else { encodingFileName = URLEncoder.encode(filename,"utf-8"); } return encodingFileName; } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JAVA進(jìn)階之HashMap底層實(shí)現(xiàn)解析
Hashmap是java面試中經(jīng)常遇到的面試題,大部分都會(huì)問(wèn)其底層原理與實(shí)現(xiàn),為了能夠溫故而知新,特地寫(xiě)了這篇文章,以便時(shí)時(shí)學(xué)習(xí)2021-11-11Mybatis-Plus 搭建與使用入門(mén)(小結(jié))
Mybatis-Plus(簡(jiǎn)稱(chēng)MP)是一個(gè) Mybatis 的增強(qiáng)工具,這篇文章主要介紹了Mybatis-Plus 搭建與使用入門(mén)(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06SpringMVC的Body參數(shù)攔截的問(wèn)題
SpringMVC對(duì)出參和入?yún)⒂蟹浅S押玫耐卣怪С?方便你對(duì)數(shù)據(jù)的輸入和輸出有更大的執(zhí)行權(quán),我們?nèi)绾瓮ㄟ^(guò)SpringMVC定義的結(jié)果做一系列處理呢,需要的朋友可以參考下2018-06-06java Socket實(shí)現(xiàn)網(wǎng)頁(yè)版在線聊天
這篇文章主要為大家詳細(xì)介紹了java Socket實(shí)現(xiàn)網(wǎng)頁(yè)版在線聊天具體代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05java 轉(zhuǎn)發(fā)和重定向區(qū)別及實(shí)例代碼
這篇文章主要介紹了java 轉(zhuǎn)發(fā)和重定向區(qū)別及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-11-11Java JDK動(dòng)態(tài)代理實(shí)現(xiàn)原理實(shí)例解析
這篇文章主要介紹了Java JDK動(dòng)態(tài)代理實(shí)現(xiàn)原理實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06零基礎(chǔ)如何系統(tǒng)的學(xué)習(xí)Java
這篇文章主要介紹了零基礎(chǔ)如何系統(tǒng)的學(xué)習(xí)Java,很多朋友糾結(jié)這個(gè)問(wèn)題,教材書(shū)不知道從何學(xué)起,今天小編給大家分享一篇教程幫助到家梳理這方面的知識(shí)2020-07-07Spring實(shí)戰(zhàn)之緩存使用condition操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之緩存使用condition操作,結(jié)合實(shí)例形式分析了Spring緩存使用condition具體配置、屬性、領(lǐng)域模型等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2020-01-01