SpringBoot系列(九)分分鐘解決文件上傳
往期推薦
SpringBoot系列(一)idea新建Springboot項(xiàng)目
SpringBoot系列(四)web靜態(tài)資源配置詳解
SpringBoot系列(五)Mybatis整合完整詳細(xì)版
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)目,如下:
?上傳一張圖片,返回可訪問(wèn)的路徑
?然后我們將這個(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è)贊表示一下。