SpringBoot結合MultipartFile類實現(xiàn)文件上傳與文件下載

前言

  1. 文件上傳下載應用場景很多吟宦。比如:我們在修改頭像的時候公黑,需要上傳頭像哆致;我們在后臺修改商品信息的時候绕德,也需要上傳商品圖片。作為Java開發(fā)者摊阀,文件上傳與文件下載功能已經(jīng)是必會的技能耻蛇。
  2. 這次使用SpringBoot實現(xiàn)單文件上傳,多文件上傳以及文件下載胞此,重點介紹MultipartFile工具類臣咖。

文件上傳到哪里合適?

我們在實現(xiàn)文件上傳功能的時候漱牵,也需要結合實際場景來決定文件的上傳位置夺蛇,一般來說有三種采納方案:

  1. 將文件上傳到工程目錄下:在一些文件存儲量很小的工程中,有一些上傳文件放置在工程本身的目錄下酣胀,但是隨著文件上傳的量越來越大刁赦,工程本身所在的文件夾容量會越來越大,不僅打包和部署的效率會降低闻镶,工程的啟動和運行也會變慢截型,所以一般不會采用這做法。
  2. 將文件上傳到工程所在服務器:將文件專門上傳到Web應用工程所在容器(如Tomcat)位于的服務器中儒溉,單獨開辟一個盤符或文件夾用于存儲上傳的圖片,這種做法讓上傳 文件與工程本身分離发钝,工程的打包和啟動效率不受到任何影響顿涣。但是如果以后出現(xiàn)了海量圖片,Web應用工程所在的服務器的效率會降低酝豪,這樣也會間接地降低應用的執(zhí)行效率涛碑,所以在上傳圖片量不大的情況下,可以采用該做法孵淘。
  3. 搭建文件服務器:一般大型的互聯(lián)網(wǎng)項目蒲障,都會為自己的文件上傳單獨架設一個文件服務器(有集群的應用,可能會有多臺文件服務器),也有獨立處理文件上傳揉阎、文件訪問的服務器庄撮。這種方案就是太燒錢。

上面分析了三種方案的特點和優(yōu)缺點毙籽。第一種一般不采取洞斯,第二種可能會采取,最常用的就是第三種方案坑赡。

MultipartFile工具類

  1. MultipartFile是SpringMVC提供簡化上傳操作的工具類烙如。
  2. 在不使用框架之前,都是使用原生的HttpServletRequest來接收上傳的數(shù)據(jù)毅否,文件是以二進制流傳遞到后端的亚铁,然后需要我們自己轉換為File類,非常麻煩螟加。使用了MultipartFile工具類之后徘溢,我們對文件上傳的操作就簡便許多了。
  3. 以下是MultipartFile工具類全部的接口方法仰迁。
方法名 返回值 作用
getContentType() String 在取文件MIME類型
getlnputStream() InputStream 獲取文件流
getName() String 獲取 form 表單中文件組件的名字
getOriginalFilename() String 獲取上傳文件件的原名
getSize() long 獲取文件的大小甸昏,單位為byte
isEmpty() boolean 是否為空
transferTo(File dest) void 將數(shù)據(jù)保存到一個目標文件中

單文件上傳

  1. 文件上傳的表單和普通表單有一點不同之處,就是需要添加enctype="multipart/form-data"這個屬性徐许,暗指該表單存在文件上傳施蜜。
    <!--單文件上傳-->
    <form action="/uploadFile" method="post" enctype="multipart/form-data">
        <p>文件:<input type="file" name="file"/></p>
        <p><input type="submit" value="上傳"/></p>
    </form>
    
    @RestController
    @Slf4j
    public class FileController {
        @PostMapping("upload")
        public String upload(MultipartFile file){
            try {
                if (file.isEmpty()){
                    return "文件為空";
                }
                //獲取文件名
                String fileName = file.getOriginalFilename();
                log.info("上傳的文件名:"+fileName);
                //獲取文件后綴名
                String suffixName = fileName.substring(fileName.lastIndexOf("."));
                log.info("文件后綴名:"+suffixName);
                //設置文件存儲路徑
                String filePath = "f:/upload/";
                String path = filePath+fileName;
                File dest = new File(path);
                //檢測是否存在該目錄
                if (!dest.getParentFile().exists()){
                    dest.getParentFile().mkdirs();
                }
                //寫入文件
                file.transferTo(dest);
                return "上傳成功!";
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "上傳失敗";
        }
    }
    

多文件上傳

  1. 文件上傳的表單和普通表單有一點不同之處雌隅,就是需要添加enctype="multipart/form-data"這個屬性翻默,暗指該表單存在文件上傳。
    <!--多文件上傳-->
    <form action="batchUpload" method="post" enctype="multipart/form-data">
        <p>文件1:<input type="file" name="file"/></p>
        <p>文件2:<input type="file" name="file"/></p>
        <p><input type="submit" value="批量上傳"/></p>
    </form>
    
    @RestController
    @Slf4j
    public class FileController {
        /**
        *  多文件上傳流程
        *      1.前端上傳多個文件
        *      2.后臺使用請求對象(MultipartHttpServletRequest)接收整個請求流
        *      3.獲取MultipartFile集合
        *      4.定義緩沖字節(jié)輸出流
        *      5.遍歷MultipartFile集合
        *      6.獲取每一個MultipartFile對象
        *      7.定義上傳路徑
        *      8.判斷上傳文件是否為空(也就是沒有上傳)
        *      9.如果不為空恰起,則通過緩沖字節(jié)輸出流寫入到上傳路徑
        */
        @PostMapping("batchUpload")
        public String batchUpload(MultipartHttpServletRequest request){
            List<MultipartFile> files = request.getFiles("file");
            MultipartFile file = null;
            BufferedOutputStream stream = null;
            for (int i = 0; i < files.size(); i++) {
                file = files.get(i);
                String filePath = "f:/upload/";
                if (!file.isEmpty()){
                    try {
                        byte[] bytes = file.getBytes();
                        stream = new BufferedOutputStream(new FileOutputStream(new File(filePath+file.getOriginalFilename())));
                        stream.write(bytes);
                        stream.close();
                    } catch (IOException e) {
                        stream = null;
                        return "第"+i+"個文件上傳失斝扌怠:"+e.getMessage();
                    }
                }else {
                    return "第"+i+"個文件上傳失敗因為文件為空";
                }
            }
            return "上傳成功";
        }
    }
    

文件下載

  1. 下載文件就是程序讀取文件流,然后響應到客戶端(輸出流操作)检盼。
    <!--文件下載-->
    <a href="download">文件下載</a>
    
    @RestController
    @Slf4j
    public class FileController {
        @GetMapping("/download")
        public String downloadFile(HttpServletRequest request, HttpServletResponse response) {
            String fileName = "boss.jpg";// 文件名
            if (fileName != null) {
                //設置文件路徑
                File file = new File("f:/upload/boss.jpg");
                //File file = new File(realPath , fileName);
                if (file.exists()) {
                    response.setContentType("application/force-download");// 設置強制下載不打開
                    response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 設置文件名
                    byte[] buffer = new byte[1024];
                    FileInputStream fis = null;
                    BufferedInputStream bis = null;
                    try {
                        fis = new FileInputStream(file);
                        bis = new BufferedInputStream(fis);
                        OutputStream os = response.getOutputStream();
                        int i = bis.read(buffer);
                        while (i != -1) {
                            os.write(buffer, 0, i);
                            i = bis.read(buffer);
                        }
                        return "下載成功";
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (bis != null) {
                            try {
                                bis.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        if (fis != null) {
                            try {
                                fis.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
            return "下載失敗";
        }
    }
    
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末肯污,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子吨枉,更是在濱河造成了極大的恐慌蹦渣,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件貌亭,死亡現(xiàn)場離奇詭異柬唯,居然都是意外死亡,警方通過查閱死者的電腦和手機圃庭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門锄奢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來失晴,“玉大人,你說我怎么就攤上這事拘央⊥科ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵堪滨,是天一觀的道長胯陋。 經(jīng)常有香客問我,道長袱箱,這世上最難降的妖魔是什么遏乔? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮发笔,結果婚禮上盟萨,老公的妹妹穿的比我還像新娘。我一直安慰自己了讨,他們只是感情好捻激,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著前计,像睡著了一般胞谭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上男杈,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天丈屹,我揣著相機與錄音,去河邊找鬼伶棒。 笑死旺垒,一個胖子當著我的面吹牛,可吹牛的內容都是我干的肤无。 我是一名探鬼主播先蒋,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宛渐!你這毒婦竟也來了竞漾?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤窥翩,失蹤者是張志新(化名)和其女友劉穎畴蹭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳍烁,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年繁扎,在試婚紗的時候發(fā)現(xiàn)自己被綠了幔荒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糊闽。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖爹梁,靈堂內的尸體忽然破棺而出右犹,到底是詐尸還是另有隱情,我是刑警寧澤姚垃,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布念链,位于F島的核電站,受9級特大地震影響积糯,放射性物質發(fā)生泄漏掂墓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一看成、第九天 我趴在偏房一處隱蔽的房頂上張望君编。 院中可真熱鬧,春花似錦川慌、人聲如沸吃嘿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兑燥。三九已至,卻和暖如春琴拧,著一層夾襖步出監(jiān)牢的瞬間降瞳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工艾蓝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留力崇,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓赢织,卻偏偏與公主長得像亮靴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子于置,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容