一、導(dǎo)包相關(guān)包
<!-- 文件上傳核心包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${fileupload.version}</version>
</dependency>
<!-- 工具包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang.version}</version>
</dependency>
二、栗子
控制層
@RestController
public class UploaderController {
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String uploadSingleFile(@RequestParam("img") MultipartFile multipartFile) throws IOException {
String imagePath = UploadUtils.saveImage(multipartFile);
return imagePath;
}
@RequestMapping(value = "/uploads", method = RequestMethod.POST)
public List<String> uploadMultipartFile(@RequestParam("img") MultipartFile[] multipartFiles) throws IOException {
List<String> imgList = new ArrayList<>();
for (MultipartFile multipartFile : multipartFiles) {
String imagePath = UploadUtils.saveImage(multipartFile);
imgList.add(imagePath);
}
return imgList;
}
}
上傳工具類
public class UploadUtils {
public static final String SAVE_IMG_FILE = "images";
public static String saveImage(MultipartFile multipartFile) throws IOException {
// 通過配置文件獲取保存的路徑 注意上線的時(shí)候要修改成服務(wù)器保存的絕對路徑
ResourceBundle bundle = ResourceBundle.getBundle("sys");
//獲取到了跟路徑
String rootPath = bundle.getString("root.upload.path");
// 獲取保存圖片名字的統(tǒng)一前綴
String imgSuffix = bundle.getString("img.suffix");
// 生成圖片保存路徑 根據(jù)日期保存
String imagePath = String.format("%s%s%s", SAVE_IMG_FILE, File.separator, DateFormatUtils.format(new Date(), "yyyyMMdd"));
/**
* 保存到服務(wù)器數(shù)據(jù)庫的路徑
*/
String savePath = String.format("%s%s%s", imagePath, File.separator, getFileName(imgSuffix, multipartFile.getOriginalFilename()));
// 拼接保存的路徑
// 根路勁 + 業(yè)務(wù)需求的路徑 + 文件名
File imgFile = new File(String.format("%s%s%s",rootPath,File.separator ,savePath));
// 創(chuàng)建保存圖片的文件
FileUtils.touch(imgFile);
// 將客服端圖片寫到文件中
FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), imgFile);
return savePath;
}
/**
* 獲取
* @param oldName
* @return
*/
public static String getFileName(String suffixName, String oldName) {
// 對圖片進(jìn)行重命名
String prefix = suffixName + DateFormatUtils.format(new Date(), "yyyyMMddHHmmss");
String suffix = oldName.substring(oldName.indexOf("."));
return prefix + suffix;
}
}
配置文件
sys.properties
# 文件大小最大值 單位kb 50M
maxUploadSize=52428800
# 單個(gè)文件限制大小 5m
maxUploadSizePerFile=5242880
# 設(shè)置文件編碼
defaultEncoding = UTF-8
# 文件上傳相關(guān)路徑
# 主路徑 修改成你自己的
root.upload.path=/Users/xxx/xxx/upload
img.suffix = IMG_
file_suffix = FILE_
mvc配置文件
<!--注意id的值是固定的 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
<!-- 默認(rèn)編碼 -->
<property name="defaultEncoding" value="${defaultEncoding}" />
<!-- 文件大小最大值 -->
<property name="maxUploadSize" value="${maxUploadSize}" />
<!-- 單個(gè)文件限制大小 -->
<property name="maxUploadSizePerFile" value="${maxUploadSizePerFile}"/>
<!-- 內(nèi)存中緩存的最大值 -->
<property name="maxInMemorySize" value="${maxInMemorySize}" />
<!-- 為true時(shí),啟用推遲文件解析,以便在UploadAction中捕獲文件大小異常-->
<property name="resolveLazily" value="${resolveLazily}"/>
</bean>
前端
- 為了能上傳文件,必須將表單的method設(shè)置為POST或者PUT
-
并將enctype設(shè)置為multipart/form-data
普通表單
<h2>單文件上傳</h2>
<form id='uploadForm' method="post" enctype="multipart/form-data">
<input type="file" name="img">
<button id='upload'>上傳</button>
</form>
<h2>多文件上傳</h2>
<form method="post" enctype="multipart/form-data">
<input type="file" name="imgs" multiple>
<button id='upload'>上傳</button>
</form>
ajax
$('#upload').click(function () {
let formData = new FormData($('#uploadForm')[0]);
$.ajax({
url:'http://localhost:8080/upload/',
dataType:'json',
type:'POST',
data: formData,
// 使數(shù)據(jù)不做處理
processData : false,
// 不要設(shè)置Content-Type請求頭
contentType : false,
success: function(data){
if (data.status == 'ok') {
alert('上傳成功!');
}
},
error:function(response){
console.log(response);
}
});
})
三、核心類介紹
MultipartFile
| 方法 | 說明 |
|---|---|
| InputStream getInputStream() | 獲取文件流 |
| getOriginalFilename() | 獲取上傳文件的原名 |
| boolean isEmpty() | 判斷文件是否為空 |
| void transferTo(File dest) | 保存文件到指定的文件中,注意父路徑一定要存在 |
| String getContentType() | 獲取文件MIME類型 |
CommonsMultipartResolver
| 屬性 | 說明 |
|---|---|
| uploadTempDir | 設(shè)置上傳文件時(shí)的臨時(shí)目錄,默認(rèn)是Servlet容器的臨時(shí)目錄。 |
| maxUploadSize | 設(shè)置允許上傳的總的最大文件大小,以字節(jié)為單位計(jì)算。當(dāng)設(shè)為-1時(shí)表示無限制,默認(rèn)是-1 |
| maxUploadSizePerFile | maxUploadSizePerFile是限制每個(gè)上傳文件的大小 |
| maxInMemorySize | 設(shè)置在文件上傳時(shí)允許寫到內(nèi)存中的最大值,以字節(jié)為單位計(jì)算,默認(rèn)是10240 |
| resolveLazily | 為true時(shí),啟用推遲文件解析,以便在UploadAction中捕獲文件大小異常。 |
| defaultEncoding | 表示用來解析request請求的默認(rèn)編碼格式,當(dāng)沒有指定的時(shí)候根據(jù)有些時(shí)候Servlet規(guī)范會使用默認(rèn)值ISO-8859-1。當(dāng)request自己指明了它的編碼格式的時(shí)候就會忽略這里指定的 |
?
四、總結(jié)
前端
- 請求方式一定要是post請求或者put請求
- 請求的conentType必須是 multipart/form-data
文件
- 對圖片進(jìn)行重命名,一般根據(jù)時(shí)間戳或者uuid生成規(guī)則,避免文件覆蓋的現(xiàn)象
- 保存的路徑也根據(jù)實(shí)際的業(yè)務(wù)場景來動態(tài)生成
多文件上傳
- 使用MultipartFile[]數(shù)組來接受,使用集合來接受保存的路徑