欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Servlet文件的上傳與下載詳解

 更新時(shí)間:2022年06月18日 10:46:26   作者:蘇瞳吶  
很多朋友不清楚在Servlet中怎么上傳下載文件,談到這個(gè)問(wèn)題,首先需要我們掌握開(kāi)發(fā)servlet的步驟,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

文件的上傳和下載

1. 文件上傳細(xì)節(jié)

要有一個(gè) form 標(biāo)簽,method-post請(qǐng)求 (因?yàn)間et有長(zhǎng)度限制)

form標(biāo)簽的屬性 encType 值必須為 multipart/form-data

表示提交的數(shù)據(jù)以多端(每一個(gè)表單項(xiàng)一個(gè)數(shù)據(jù)段)的形式進(jìn)行拼接,然后以二進(jìn)制流的形式發(fā)送給服務(wù)器

在 form 標(biāo)簽中使用 input type="file" 添加上傳的文件

編寫(xiě)服務(wù)器代碼 (Servlet接收),接受處理上傳的數(shù)據(jù)

文件上傳http請(qǐng)求信息:

請(qǐng)求頭:Content-Type: multipart/form-data; boundary=------WebKitFormBoundaryCd3g75eOt35olUs7

解析:

  • Content-Type 表示提交的數(shù)據(jù)類(lèi)型
  • multipart/form-data 表示以流的形式分段提交服務(wù)器
  • boundary 表示每段數(shù)據(jù)的分隔符,值:----WebKitFormBoundarylXiF4fEzpo9c8L4p 是瀏覽器每次隨機(jī)生成的,它就是每段數(shù)據(jù)的分界符。在每段里面 第一行是對(duì)表單項(xiàng)的描述,然后有個(gè)空行,下面是提交的值。

請(qǐng)求體:

------WebKitFormBoundaryCd3g75eOt35olUs7
Content-Disposition: form-data; name="username"

zhu
------WebKitFormBoundaryCd3g75eOt35olUs7
Content-Disposition: form-data; name="photo"; filename="head.jpg"
Content-Type: image/jpeg

文件的信息(很長(zhǎng)這里省略了)
------WebKitFormBoundaryCd3g75eOt35olUs7--

因?yàn)榭蛻舳耸且园戳鞯姆绞教峤皇牵晕覀円戳鞯姆绞将@取,不能這樣: req.getParameter("username");

正確用法:

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("上傳成功");
    ServletInputStream inputStream = req.getInputStream(); // 先得到 字節(jié)輸入流
    byte[] buffer = new byte[1024]; // 緩沖區(qū)
    int readCount = 0;
    while ((readCount = inputStream.read(buffer)) != -1) { // 打印出來(lái)的就是上面全部的請(qǐng)求體
        System.out.println(new String(buffer, 0, readCount));
    }
}

2. 文件上傳

這種文件上傳(常用)有很多第三方提供好的API我們使用進(jìn)行了,可以幫我們對(duì)收到的數(shù)據(jù)進(jìn)行解析。

例如:commons-fileupload-1.2.1.jar (依賴(lài)于 commons-io-1.4.jar

  • 導(dǎo)入兩個(gè)jar包
  • 解析

關(guān)鍵的類(lèi):

  • ServletFileUpload 類(lèi):用于解析上傳的數(shù)據(jù)
  • FileItem 類(lèi):每一個(gè)表單項(xiàng)
//ServletFileUpload中的方法
// 判斷當(dāng)前上傳的數(shù)據(jù)是否是多端的格式,不是解析不了
public boolean ServletFileUpload.isMultipartContent(HttpServletRequest req) 
// 解析上傳的數(shù)據(jù),F(xiàn)ileItem表示每一個(gè)表單項(xiàng)
public List<FileItem> parseRequest(HttpServletRequest req)
//FileItem中方法
// 判斷當(dāng)前這個(gè)表單項(xiàng)是普通的表單項(xiàng)還是文件上傳的類(lèi)型,true表示普通的
public boolean isFormField()    
// 獲取表單項(xiàng)name屬性值
public String getFieldName()
// 獲取當(dāng)前表單項(xiàng)的值
public String getString() // 可傳入字符集,防止亂碼,一開(kāi)始req.setCharacterEncoding("UTF-8");也行
// 獲取上傳的文件名
public String getName()
// 將上傳的文件寫(xiě)道 參數(shù)file所指向的磁盤(pán)位置
public void write(File file)

Servlet上傳文件示例:

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("UTF-8"); // 防止亂碼
    resp.setContentType("text/html; charset=utf-8");
    String savePath = getServletContext().getRealPath("/WEB-INF/uploadFile"); //保存的路徑
    // 首先判斷上傳的數(shù)據(jù)是否是多段的數(shù)據(jù)
    if (ServletFileUpload.isMultipartContent(req)) {
        FileItemFactory fileItemFactory = new DiskFileItemFactory(); // 創(chuàng)建FileItemFactory工廠的實(shí)現(xiàn)類(lèi),
        // 創(chuàng)建用于解析上傳數(shù)據(jù)的工具類(lèi)
        ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory); 
        try {
            List<FileItem> list = servletFileUpload.parseRequest(req); // 解析,得到每一個(gè)表單項(xiàng)
            for (FileItem fileItem : list) {
                if (fileItem.isFormField()) { // 普通表單項(xiàng)
                    System.out.print("表單項(xiàng)的name屬性值:" + fileItem.getFieldName());
                    System.out.println("  表單項(xiàng)的value:" + fileItem.getString("UTF-8"));
                } else { // 文件類(lèi)型
                    System.out.print("文件的name屬性值:" + fileItem.getFieldName());
                    System.out.println("  上傳的文件名:" + fileItem.getName());
                    // 一般會(huì)保存到用戶訪問(wèn)不能直接訪問(wèn)的目錄下 File.separator是系統(tǒng)默認(rèn)路徑分隔符,win下是 / 
                    // (下面這是保存到了部署的真是目錄下,保存到了服務(wù)器中)
                    // 可以用UUID保證文件名的唯一性,防止文件覆蓋。
                    // 防止單個(gè)目錄文件過(guò)多影響讀寫(xiě)速度,還可以使用目錄生成算法分散儲(chǔ)存
                    fileItem.write(new File(savePath + File.separator + fileItem.getName()));
                    //fileItem.delete(); //關(guān)閉資源
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. 文件下載

客戶端 ->(發(fā)送請(qǐng)求告訴服務(wù)器我要下載什么文件) -> 服務(wù)器

服務(wù)器干的內(nèi)容:

  • 獲取要下載的文件名
  • 讀取要下載的文件內(nèi)容
  • 通過(guò)響應(yīng)頭告訴客戶端返回的數(shù)據(jù)類(lèi)型是什么 (和要下載的類(lèi)型一致)
  • 告訴的客戶端收到的數(shù)據(jù)是用于下載使用(還是用響應(yīng)頭設(shè)置)
  • 把下載的的文件內(nèi)容回傳給客戶端下載

這個(gè)也能用 commons-io-1.4.jar 的IOUtils 類(lèi):

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("UTF-8"); // 防止亂碼
    resp.setCharacterEncoding("UTF-8");
    //1.獲取要下載的文件名路徑名,并通過(guò)ServletContext讀取讀取文件
    String downloadFileName = "head.jpg"; // 我們這里寫(xiě)死了
    ServletContext servletContext = getServletContext();
    String savePath = servletContext.getRealPath("/WEB-INF/upload"); //以前上傳文件保存的目錄
    String downloadPath = savePath + File.separator + downloadFileName;
    //2.告訴客戶端返回的類(lèi)型
    String downloadType = servletContext.getMimeType(downloadPath); //獲取要下載文件的類(lèi)型 (這個(gè)是image/jpeg)
    resp.setContentType(downloadType); // (和要下載的類(lèi)型一樣)
    //3.告訴客戶端收到的數(shù)據(jù)是用于下載的,不是直接顯示在頁(yè)面的
    // Content-Disposition表示收到的數(shù)據(jù)怎么處理,attachment表示附件下載使用,filename表示下載文件的名字
    // filename名可以不和本地的名字一樣,當(dāng)有中文時(shí)會(huì)亂碼,因?yàn)閔ttp協(xié)議設(shè)置的的時(shí)候不支持中文,需要進(jìn)行url編碼
    /resp.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
    resp.setHeader("Content-Disposition", 
                   "attachment;filename=" + URLEncoder.encode(downloadFileName, "UTF-8"));
    InputStream resourceAsStream = servletContext.getResourceAsStream(downloadPath); 
    // getResourceAsStream() 傳入文件路徑,讀取文件!!!!!!!!!!!!!
    // 4.commons-io-1.4.jar中有IOUtils我們可以直接用,不用自己read() write()了
    ServletOutputStream outputStream = resp.getOutputStream(); // 獲取響應(yīng)的輸出流
    IOUtils.copy(resourceAsStream, outputStream); 
    // 讀取輸入流的信息復(fù)制給輸出流,輸出給客戶端,傳入一個(gè)輸入流和輸出流 (字節(jié)字符流都行)
}

到此這篇關(guān)于Servlet文件的上傳與下載詳解的文章就介紹到這了,更多相關(guān)Servlet上傳下載文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Log4j如何屏蔽某個(gè)類(lèi)的日志打印

    Log4j如何屏蔽某個(gè)類(lèi)的日志打印

    這篇文章主要介紹了Log4j如何屏蔽某個(gè)類(lèi)的日志打印,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • JAVA實(shí)現(xiàn)深拷貝的幾種方式代碼

    JAVA實(shí)現(xiàn)深拷貝的幾種方式代碼

    這篇文章主要給大家介紹了關(guān)于JAVA實(shí)現(xiàn)深拷貝的幾種方式,在Java中深拷貝和淺拷貝是用來(lái)復(fù)制對(duì)象的兩種不同方式,深拷貝會(huì)對(duì)所有數(shù)據(jù)類(lèi)型進(jìn)行拷貝,包括對(duì)象所包含的內(nèi)部對(duì)象,需要的朋友可以參考下
    2023-09-09
  • 詳解hibernate雙向多對(duì)多關(guān)聯(lián)映射XML與注解版

    詳解hibernate雙向多對(duì)多關(guān)聯(lián)映射XML與注解版

    本篇文章主要介紹了詳解hibernate雙向多對(duì)多關(guān)聯(lián)映射XML與注解版,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 解決spring中redistemplate不能用通配符keys查出相應(yīng)Key的問(wèn)題

    解決spring中redistemplate不能用通配符keys查出相應(yīng)Key的問(wèn)題

    這篇文章主要介紹了解決spring中redistemplate不能用通配符keys查出相應(yīng)Key的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • Java實(shí)現(xiàn)多個(gè)數(shù)組間的排列組合

    Java實(shí)現(xiàn)多個(gè)數(shù)組間的排列組合

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多個(gè)數(shù)組間的排列組合,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 詳解如何將JAR包發(fā)布到Maven中央倉(cāng)庫(kù)

    詳解如何將JAR包發(fā)布到Maven中央倉(cāng)庫(kù)

    這篇文章主要介紹了詳解如何將JAR包發(fā)布到Maven中央倉(cāng)庫(kù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • 自從在 IDEA 中用了熱部署神器 JRebel 之后,開(kāi)發(fā)效率提升了 10(真棒)

    自從在 IDEA 中用了熱部署神器 JRebel 之后,開(kāi)發(fā)效率提升了 10(真棒)

    在javaweb開(kāi)發(fā)過(guò)程中,使用熱部署神器 JRebel可以使class類(lèi)還是更新spring配置文件都能立馬見(jiàn)到效率,本文給大家介紹JRebel的兩種安裝方法,小編建議使用第二種方法,具體安裝步驟跟隨小編一起看看吧
    2021-06-06
  • Java replaceAll()方法報(bào)錯(cuò)Illegal group reference的解決辦法

    Java replaceAll()方法報(bào)錯(cuò)Illegal group reference的解決辦法

    這篇文章主要給大家介紹了關(guān)于Java replaceAll()方法報(bào)錯(cuò)Illegal group reference的解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • java:程序包org.springframework.boot不存在的完美解決方法

    java:程序包org.springframework.boot不存在的完美解決方法

    最近項(xiàng)目中運(yùn)行的時(shí)候提示了"java: 程序包org.springframework.boot不存在",下面這篇文章主要給大家介紹了關(guān)于java:程序包org.springframework.boot不存在的完美解決方法,需要的朋友可以參考下
    2023-05-05
  • JVM GC 垃圾收集梳理總結(jié)

    JVM GC 垃圾收集梳理總結(jié)

    這篇文章主要介紹了JVM GC 垃圾收集梳理總結(jié),GC是一種自動(dòng)的存儲(chǔ)管理機(jī)制。當(dāng)一些被占用的內(nèi)存不再需要時(shí),就應(yīng)該予以釋放,這種存儲(chǔ)資源管理,稱(chēng)為垃圾回收
    2022-07-07

最新評(píng)論