SpringBoot系列(九)文件上傳的正確姿勢(shì)

SpringBoot系列(九)分分鐘解決文件上傳

往期推薦

SpringBoot系列(一)idea新建Springboot項(xiàng)目

SpringBoot系列(二)入門知識(shí)

springBoot系列(三)配置文件詳解

SpringBoot系列(四)web靜態(tài)資源配置詳解

SpringBoot系列(五)Mybatis整合完整詳細(xì)版

SpringBoot系列(六)集成thymeleaf詳解版

Springboot系列(七) 集成接口文檔swagger,使用席揽,測(cè)試

SpringBoot系列(八)分分鐘學(xué)會(huì)Springboot多種解決跨域方式

1.項(xiàng)目搭建與配置

?我們直接創(chuàng)建一個(gè)包含web依賴的項(xiàng)目就好了唯灵。
然后需要在配置文件配置文件上傳的一些設(shè)置。這里使用yml文件作為配置文件笔呀,如果不懂語(yǔ)法的偶器,請(qǐng)移步前面的系列三觉壶,里面有詳細(xì)解釋脑题。

server:
  port: 8095

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 30MB
  • max-file-size 設(shè)置能接受的文件最大的大小,記得是MB,或KB
  • max-request-size 設(shè)置一次上傳的所有文件的大小铜靶。

?默認(rèn)大小為1MB

?除了可以用配置文件配置還可利用java配置叔遂,如下

@Bean
public MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    //上傳的單個(gè)文件最大值   KB,MB 這里設(shè)置為10MB
    DataSize maxSize = DataSize.ofMegabytes(10);
    DataSize requestMaxSize = DataSize.ofMegabytes(30);
    factory.setMaxFileSize(maxSize);
    /// 設(shè)置一次上傳文件的總大小
    factory.setMaxRequestSize(requestMaxSize);
    return factory.createMultipartConfig();
}

?這個(gè)方法可以放在啟動(dòng)類里面,也可以自己放置在一個(gè)配置類里面争剿,讓項(xiàng)目啟動(dòng)的時(shí)候能正常加載就行已艰。

2.文件上傳

?單文件上傳,我們需要用后端接受并將文件存儲(chǔ)到項(xiàng)目里面或者是自己定義路徑秒梅。這里以圖片作為上傳的文件旗芬。并且將文件上傳到項(xiàng)目里面。

@RestController
@RequestMapping("/file")
public class FileController {
    @PostMapping("/uploadFile")
    public String uploadFile(MultipartFile file, HttpServletRequest request)  {
        if (file.isEmpty()){
            return "上傳的文件不能為空捆蜀!請(qǐng)重新上傳";
        }
        if (file.getSize()<=0){
            return "上傳的文件大小需要大于0kb";
        }
        System.out.println(file.getContentType());//image/png
        Date date = new Date();
        Long time = date.getTime();
        String originFileName = file.getOriginalFilename();//獲取文件原始的名稱
        String newFileName = time+originFileName;
        //獲取項(xiàng)目運(yùn)行的絕對(duì)路徑
        String filePath = System.getProperty("user.dir");

        //由于我是創(chuàng)建的多模塊項(xiàng)目疮丛,所以獲取到的項(xiàng)目運(yùn)行路徑為外層的項(xiàng)目路徑,
        // 這時(shí)候我們就需要在項(xiàng)目相對(duì)路徑這里加上項(xiàng)目的名稱demo-upload
        String newFilePath = filePath+"\\demo-upload\\src\\main\\resources\\static\\images\\";

        //當(dāng)然你也可以自己設(shè)置一個(gè)絕對(duì)路徑用于圖片上傳辆它,文件上傳誊薄。
        //比如說(shuō):D:\\images\\
        File file1 = new File(newFilePath);

        if (!file1.exists()){
            file1.mkdirs();
        }
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(newFilePath+newFileName);
            fileOutputStream.write(file.getBytes());
            fileOutputStream.flush();
            fileOutputStream.close();
            return "localhost:8095/images/"+newFileName;
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
        return "上傳失敗";
    }
}

代碼說(shuō)明:

?在代碼里,我們可以利用參數(shù)file來(lái)判斷這個(gè)文件是否為空锰茉,或者將這個(gè)文件的后綴名拿出來(lái)呢蔫,判斷這個(gè)文件的類型是否符合我們的要求,利用getContentType() 方法,如果你是上傳的png圖片片吊,那么打印出來(lái)的就是image/png 其他類型的圖片就是其他類型绽昏。我們?yōu)榱藚^(qū)分圖片,可以利用當(dāng)前時(shí)間的getTime方法獲得的數(shù)字來(lái)作為圖片的前綴俏脊,也可以用其他的數(shù)字或者字符串全谤。都不想說(shuō)了,碼字太累了爷贫。接下來(lái)獲取當(dāng)前項(xiàng)目運(yùn)行的路徑认然,由于我是創(chuàng)建的多模塊項(xiàng)目,所以這個(gè)獲取的路徑需要再加上項(xiàng)目名稱漫萄,后面加上我們需要上傳的文件存儲(chǔ)的位置卷员,一般在resources文件下面。然后判斷這個(gè)存儲(chǔ)文件的文件夾是否存在腾务,如果不存在就需要?jiǎng)?chuàng)建一個(gè)文件毕骡。然后利用字節(jié)流,將數(shù)據(jù)寫到文件中窑睁,返回可訪問(wèn)的路徑挺峡。

?前端代碼,我直接在static目錄下面創(chuàng)建了一個(gè)upload.html文件担钮,然后我們?cè)谖募锩鎸懭胍幌聝?nèi)容

<p>單文件上傳</p>
<form action="/file/uploadFile" method="POST" enctype="multipart/form-data">
    文件:<input type="file" name="file"/>
    <input type="submit" />
</form>

?它的action對(duì)應(yīng)了我們controller里面訪問(wèn)上傳文件的對(duì)應(yīng)的方法的路徑,method屬性是post尤仍,與后端一致箫津。type為file的input框的name屬性需要與controller里面的接受對(duì)象MultipartFile 一致,如果不一致的話后端無(wú)法接受到數(shù)據(jù)宰啦。如果你已經(jīng)寫好后端苏遥,而前端后端參數(shù)不一致,你可以給后端參數(shù)加上一個(gè)注解赡模。@RequestParam("file") 這個(gè)注解放在MultipartFile的前面田炭,這樣即使你的參數(shù)名字不是file,也能正確接受到數(shù)據(jù)漓柑。

?將文件上傳之后教硫,那個(gè)返回的路徑應(yīng)該是不能直接訪問(wèn)到圖片的,會(huì)顯示404辆布,我們需可以添加以下配置瞬矩。

@Configuration
public class ResourceConfigAdapter implements WebMvcConfigurer {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //獲取文件的真實(shí)路徑
        String path = System.getProperty("user.dir")+"\\demo-upload\\src\\main\\resources\\static\\images\\";
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith("win")) {
            registry.addResourceHandler("/images/**").
                    addResourceLocations("file:" + path);
        }

    }
}

?這里的java動(dòng)態(tài)配置比利用的yml的配置更靈活,在知道文件要存儲(chǔ)的位置的情況下锋玲,可以自己在yml文件里面加配置景用。然后我們運(yùn)行項(xiàng)目,如下:


image

?上傳一張圖片,返回可訪問(wèn)的路徑


image

?然后我們將這個(gè)URL復(fù)制到瀏覽器惭蹂,運(yùn)行伞插,就能訪問(wèn)圖片了割粮。

?這是單文件上傳,然后可能你需要做多文件上傳媚污,很簡(jiǎn)單穆刻,后端做一個(gè)循環(huán)就行了,然后利用MultipartFile的數(shù)組接受文件杠步,對(duì)前端做一點(diǎn)修改氢伟。

 @PostMapping("/uploadFiles")
public String uploadFiles(MultipartFile[] files,HttpServletRequest request) {
    StringBuilder paths = new StringBuilder();
    for (MultipartFile file:files) {
        //中間的代碼和上面的一樣
        try {
            //這里根據(jù)實(shí)際情況修改,可以用數(shù)組
            paths.append("localhost:8095/images/"+newFileName+"\n");
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
    return paths.toString();
}

?前端稍微修改一下

<p>多文件上傳</p>

<form action="/file/uploadFiles" method="POST" enctype="multipart/form-data">
    文件:<input type="file" name="files" multiple="multiple"/>
    <input type="submit"/>
</form>

?這就完成了多文件的上傳幽歼,在上傳的時(shí)候你需要按住Ctrl鍵朵锣,然后選中多個(gè)文件,就能上傳了甸私。

3.總結(jié)

?本文講解了單文件诚些,多文件上傳,然后對(duì)文件的上傳限制條件與訪問(wèn)添加了一些配置皇型。如果你覺(jué)得本文對(duì)你有用诬烹,點(diǎn)個(gè)贊表示一下。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弃鸦,一起剝皮案震驚了整個(gè)濱河市绞吁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唬格,老刑警劉巖家破,帶你破解...
    沈念sama閱讀 210,835評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異购岗,居然都是意外死亡汰聋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門喊积,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烹困,“玉大人,你說(shuō)我怎么就攤上這事乾吻∷杳罚” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 156,481評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵溶弟,是天一觀的道長(zhǎng)女淑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)辜御,這世上最難降的妖魔是什么鸭你? 我笑而不...
    開(kāi)封第一講書人閱讀 56,303評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上袱巨,老公的妹妹穿的比我還像新娘阁谆。我一直安慰自己,他們只是感情好愉老,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,375評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布场绿。 她就那樣靜靜地躺著,像睡著了一般嫉入。 火紅的嫁衣襯著肌膚如雪焰盗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,729評(píng)論 1 289
  • 那天咒林,我揣著相機(jī)與錄音熬拒,去河邊找鬼。 笑死垫竞,一個(gè)胖子當(dāng)著我的面吹牛澎粟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播欢瞪,決...
    沈念sama閱讀 38,877評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼活烙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了遣鼓?” 一聲冷哼從身側(cè)響起啸盏,我...
    開(kāi)封第一講書人閱讀 37,633評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎譬正,沒(méi)想到半個(gè)月后宫补,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,088評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡曾我,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,443評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了健民。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抒巢。...
    茶點(diǎn)故事閱讀 38,563評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖秉犹,靈堂內(nèi)的尸體忽然破棺而出蛉谜,到底是詐尸還是另有隱情,我是刑警寧澤崇堵,帶...
    沈念sama閱讀 34,251評(píng)論 4 328
  • 正文 年R本政府宣布型诚,位于F島的核電站,受9級(jí)特大地震影響鸳劳,放射性物質(zhì)發(fā)生泄漏狰贯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,827評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涵紊。 院中可真熱鬧傍妒,春花似錦、人聲如沸摸柄。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,712評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)驱负。三九已至嗦玖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跃脊,已是汗流浹背宇挫。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,943評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匾乓,地道東北人捞稿。 一個(gè)月前我還...
    沈念sama閱讀 46,240評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拼缝,于是被迫代替她去往敵國(guó)和親娱局。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,435評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容