多文件上傳:從前台到后台代碼實現


一、業務場景

   項目中有個功能模塊是商品管理,其中需要使用到圖片上傳,而且是多文件上傳,這是比較常規的操作,就自己來寫這個功能。

商品管理這個功能,除去圖片操作之外,常規的增、刪、改、查很快完成,然后在把圖片相關操作添加進來。

二、需求分析

   自己以前開發的項目中,涉及文件上傳的功能倒是不少,可是涉及多文件上傳的功能還真沒有接觸過。可是這不影響自己來做

這個功能,正好可以借此機會學習學習如何實現多文件上傳的功能。要點有兩個,一個是前端代碼怎么添加多個文件,一個是后台

如何來接收多個文件。搞清楚這兩個問題之后,剩下的事情會簡單得多。

三、解決方案

  自己首先完成多文件上傳的前端代碼,核心代碼是創建一個FormData對象,然后獲取頁面中選擇的文件數組之后,

循環遍歷添加多個文件,並且多個文件是添加到同一個字段上,代碼如下

var formData = new FormData();
//循環獲取上傳個文件
for (var i = 0, len = $("#upload_file")[0].files.length; i < len; i++) {
var dataTemp = $("#upload_file")[0].files[i];
//console.log("dataTemp--->", dataTemp);
var fileName = dataTemp.name;
var fivarype = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();
if(fivarype !== '.jpg' && fivarype !== '.png'){
return layer.msg('錯誤提示:只能上傳jpg或者png格式的圖片!');
}
var fileSize = dataTemp.size;
var limitSize = 2 * 1024 * 1024;
//console.log("fileSize--->", fileSize);
if(fileSize > limitSize){
return layer.msg('錯誤提示:文件大小不能超過2M!');
}
formData.append("files", dataTemp);
}

這樣寫有一個好處,可以單獨判斷每一個選中的文件是否符合特定的格式,大小是否符合要求,在前端可以做一個

簡單的過濾。將所有的文件對象都添加到files這個字段之上,多單文件上傳的時候自己以為只能添加一次,可是做

好這個功能之后,發現它可以添加多次。有的網友是直接添加formData.append("files",$("#upload_file")[0]); 這樣也沒問題,

只是在選擇文件的時候,不會做相關的校驗。html代碼如下,

<!-- 圖片文件選擇 -->
<div style="display:none;">
<input type="file" name="file" id="upload_file" onchange="do_upload()" multiple="multiple" accept=".jpg,.png">
</div>

上傳文件時,自己使用的是ajax請求來發送數據,代碼如下,

var loadStatus = layer.load(1);
//提交數據
$.ajax({
url: contextPath + '/goods/upload',
type: 'post',
headers:{
'loginToken': "Bearer " + localStorage.loginToken
},
data: formData,
cache: false,//上傳文件無需緩存
contentType: false,//必須
processData: false,//用於對data參數進行序列化處理 這里必須false
success: function (result) {
/**
{
code: -1
count: null
data: null
message: "未獲取到上傳文件信息"
status: "失敗"
url: null
}
*/
//console.log("result--->", result);
if (result.code === 0) {
layer.msg("提示信息:圖片上傳成功!");
var tempArr = result.data;
for(var i = 0, len = tempArr.length; i < len; i++){
filePathList[filePathList.length] = tempArr[i];
}
//console.log("圖片上傳-filePathList--->", filePathList);
handlerShowPicture();
}else {
layer.msg("錯誤提示: 圖片上傳失敗");
}

$("#upload_file").parent().html('<input type="file" name="file" id="upload_file" onchange="do_upload()" multiple="multiple" accept=".jpg,.png">');
layer.close(loadStatus);
// setTimeout(function () {
// //延遲1 s 在關閉彈出窗口
// layer.closeAll();
// }, 1000);
},
error: function () {
layer.msg('錯誤提示:上傳圖片出現異常,請稍后重試!');
layer.close(loadStatus);
// setTimeout(function () {
// //延遲1 s 在關閉彈出窗口
// layer.closeAll();
// }, 1000);
$("#upload_file").parent().html('<input type="file" name="file" id="upload_file" onchange="do_upload()" multiple="multiple" accept=".jpg,.png">');
},
timeout: 180000,
complete: function () {
//$.messager.progress('close');
}
});

這種方式簡單可用,在寫過的很多項目中都是使用這種方式來上傳文件。

 

后端代碼經過反反復復的摸索之后,操作依賴也並不復雜,一個是接收文件數組的時候,直接在方法的形參中進行接收,代碼如下

/**
* @description: 商品圖片上傳
* @date: 2022/1/28 15:31
* @param : MultipartFile[]
* @return: ResultVO
*/
//@PostMapping("/upload")
@RequestMapping(value="/upload",method= RequestMethod.POST,consumes="multipart/form-data")
public ResultVO uploadFile(@RequestParam MultipartFile[] files){
List<String> filePathList = null;
try{
if(files == null){
return ResultVOUtil.error(-1, "文件不存在");
}

for(int i = 0, len = files.length; i < len; i++){
MultipartFile file = files[i];

long fileSize = file.getSize();

if(fileSize > giftLimitSize || fileSize == 0){
log.error("文件大小超出限制:" + fileSize);
return ResultVOUtil.error(-1, "只能上傳大小2M以內的圖片");
}

String fileName = file.getOriginalFilename();
if(StringUtils.isBlank(fileName)){
log.error("文件名稱錯誤:" + fileName);
return ResultVOUtil.error(-1, "文件名稱錯誤");
}

String fileSuffixName = fileName.substring(fileName.lastIndexOf(".") + 1);
if(!typeSet.contains(fileSuffixName)){
log.error("文件后綴名錯誤:" + fileSuffixName);
return ResultVOUtil.error(-1, "文件后綴名錯誤");
}
}

filePathList = this.goodsManageService.uploadPicture(files);

}catch (Exception ex){
log.error("圖片上傳操作異常--->" + ex.getMessage());
ex.printStackTrace();
}

log.info("圖片上傳返回數據為--->" + filePathList);
if(Objects.equal(filePathList, null)){
return ResultVOUtil.error(-1, "圖片上傳操作失敗");
}else{
return ResultVOUtil.success("上傳成功", filePathList);
}
}

在service中具體的處理邏輯如下,
@Override
public List<String> uploadPicture(MultipartFile[] files) throws Exception {
if(files == null){
log.error("參數-files-錯誤{}:", files);
return null;
}

String targetPath = String.join(File.separator, linuxPath, "3");
File tempPath = new File(targetPath);
if(!tempPath.exists()){
tempPath.mkdirs();
}

String destFileName = "";
List<String> filePathList = new ArrayList<String>();
try{
for(int i = 0, len = files.length; i < len; i++) {
MultipartFile file = files[i];
String fileName = file.getOriginalFilename();

String fileSuffixName = fileName.substring(fileName.lastIndexOf(".") + 1);

destFileName = CommonUtil.getUUID() + "." + fileSuffixName;
String targetFile = String.join(File.separator, targetPath, destFileName);
File destFile = new File(targetFile);
if(!destFile.exists()){
destFile.createNewFile();
}
file.transferTo(destFile);

String returnPath = File.separator + String.join(File.separator, "3", destFileName);
boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");
if(isWin){
//windows 系統 進行路徑替換 將 / 替換為 \\
returnPath = returnPath.replaceAll("\\\\", "/");
}

filePathList.add(returnPath);
}
}catch (Exception ex){
log.error("文件保存異常:" + ex.getMessage());
return null;
}


return filePathList;
}

主要做的一個操作就是接收文件數組,然后將文件保存到自己指定的一個目錄下面即可,核心代碼是

file.transferTo(destFile);file表示文件數組中的對象,destFile表示目標文件的全路徑,包含文件后綴名,
這句代碼的含義就是將上傳的文件保存到指定的文件當中。最后按照自己業務的要求返回指定的文件路徑,不是文件的
全路徑,因為在顯示圖片的時候傳的參數是一個相對路徑,后台處理的時候加上路徑前綴即可。圖片顯示的方法如下,
public void showPicture(String filePath, HttpServletResponse response) throws Exception {
if(StringUtils.isBlank(filePath)){
log.error("參數-filePath-錯誤");
return;
}
String realPath = linuxPath + filePath;
String result = "-1";
File file = new File(realPath);
response.setContentType("image/jpeg");

try (FileInputStream fis = new FileInputStream(realPath);
OutputStream os = response.getOutputStream();){
int len = 0;
byte[] buffer = new byte[1024];
while ((len = fis.read(buffer)) != -1){
os.write(buffer, 0, len);
}
os.flush();
} catch (Exception ex) {
log.error("圖片顯示服務錯誤:" + ex.getMessage());
}
}
至此整個多文件上傳的功能,全部搞定,功能完成,效果如下

 

 

 

 

參考博文:

前端代碼

http://www.manongjc.com/detail/22-chxcnufnrzpbzfn.html

后台代碼

https://www.cnblogs.com/ainyi/p/11345714.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM