菜鳥的springboot項目圖片上傳及圖片路徑分析
說明
本文記錄一下springboot項目的圖片上傳的相關知識,主要解決項目打成jar包部署時的圖片路徑問題,本文會持續更新,不斷地擴充
本文僅爲記錄學習軌跡,如有侵權,聯繫刪除
一、圖片路徑分析
springboot項目在還沒打包時,很多人喜歡把圖片上傳後,保存在項目的靜態資源下,就像下面的圖片那樣
這樣好像看來沒問題,在還沒打成jar包時,在idea啓動運行正常,圖片也確實存儲到了靜態資源下的images文件夾中,但是一旦打包成jar包後,運行jar包時,發現圖片存儲路徑出錯了,圖片並不會存儲到靜態資源下的images文件夾中,而是到服務器的用戶下的路徑那裏去,如果把打包後的jar包在自己電腦運行,按照上面的代碼,圖片就會存儲到C盤下對應的電腦用戶那裏
這是因爲打包後會生成一個jar包,這個jar可以解壓,發現裏面的classes就打包有靜態資源,而且上面的代碼String path = System.getProperty("user.dir");
在idea啓動運行時會獲取到項目的根路徑,所以在idea啓動運行時可以將圖片保存在項目下的images文件夾裏面,而打包成一個jar後,用java -jar jar包名稱
啓動時,獲取的確是C盤下的用戶路徑,而不會獲取到jar所在的目錄,跟不會獲取到jar裏面的classes文件的路徑
這種獲取圖片路徑並存儲的方式肯定不是我想要的,我想要的效果是,即使打成jar包後,可以在jar包所在目錄下自動生成一個文件夾,上傳的圖片就保存在這個文件夾中,這樣就不論你jar包部署在哪裏,都可以獲取到jar所在根目錄,並自動生成一個文件夾保存上傳的圖片
這樣的話部署就方便多了
二、實現圖片上傳
(1)單文件上傳(非異步)
我們知道項目打包後的jar包都在target文件夾裏面,也就是說target所在文件夾纔是jar包所在的路徑,所以,圖片存儲的位置就應該在target裏面,這樣在打成jar包後,就可以獲取jar包所在目錄,實現上面分析的功能
前端代碼
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>單文件上傳</title>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<script th:src="@{/js/jquery.min.js}"></script>
</head>
<body>
<div th:if="${uploadStatus}" style="color: red" th:text="${uploadStatus}">上傳成功</div>
<form th:action="@{/singleUploadFile}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label>單文件上傳</label>
<input class="form-control-file" type="file" name="file" required="required" />
</div>
<input id="submit" type="submit" value="上傳" />
</form>
</body>
</html>
後端對應控制器的代碼
//來到單文件上傳頁面(非異步)
@GetMapping("/toSingleUpload")
public String singleUpload() throws FileNotFoundException {
return "singleUpload";
}
//上傳圖片(非異步)
@PostMapping("/singleUploadFile")
public String singleUploadFile(MultipartFile file, Model model){
String fileName=file.getOriginalFilename(); //獲取文件名以及後綴名
//fileName= UUID.randomUUID()+"_"+fileName;//重新生成文件名(根據具體情況生成對應文件名)
//獲取jar包所在目錄
ApplicationHome h = new ApplicationHome(getClass());
File jarF = h.getSource();
//在jar包所在目錄下生成一個upload文件夾用來存儲上傳的圖片
String dirPath = jarF.getParentFile().toString()+"/upload/";
System.out.println(dirPath);
File filePath=new File(dirPath);
if(!filePath.exists()){
filePath.mkdirs();
}
try{
//將文件寫入磁盤
file.transferTo(new File(dirPath+fileName));
//上傳成功返回狀態信息
model.addAttribute("uploadStatus","上傳成功");
}catch (Exception e){
e.printStackTrace();
//上傳失敗,返回失敗信息
model.addAttribute("uploadStatus","上傳失敗:"+e.getMessage());
}
//攜帶上傳狀態信息回調到文件上傳頁面
return "singleUpload";
}
在idea啓動運行,圖片保存在target下的upload,打成jar包後運行,則會在jar所在目錄下自動生成upload文件存儲上傳的圖片
實現了圖片的上傳後,如何獲取圖片,如果沒法獲取那上傳圖片就沒意思了,假設我將jar放在路徑"E:\文件上傳“,圖片就在文件夾"E:\文件上傳\upload\1.png"裏面,如果用這種方式<img src="E:\文件上傳\upload\1.png">
獲取圖片是不行的,首先是訪問不了項目外的資源,其次這個路徑應該是動態的,隨着jar包的路徑變動的,爲了實現這兩點就需要做個視圖解析器
這樣訪問”/upload/“就會自動訪問到jar包下的upload文件夾,也就可以訪問圖片了
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>獲取圖片</title>
</head>
<body>
<!--這樣訪問”/upload/“就會自動訪問到jar包下的upload文件夾,也就可以訪問圖片了-->
<img src="/upload/1.png">
</body>
</html>
這樣不論是在idea裏運行還是打包運行,都可以完美的獲取上傳和獲取圖片
(2)單文件上傳(異步)
在(1)非異步單文件上傳的基礎,再實現異步單文件上傳
前端代碼
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>無刷文件上傳</title>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<script th:src="@{/js/jquery.min.js}"></script>
</head>
<body>
<div th:if="${msg}" style="color: red" th:text="${msg}">上傳成功</div>
<form id="form" th:action="@{/ajaxUploadFile}" >
<div class="form-group">
<label>無刷文件上傳</label>
<input type='file' style='margin: 5px;' name='files' required='required'>
<input id="submit" type="button" value="上傳" onclick="ajaxUpload()" style="margin-top: 10px"/>
</div>
</form>
<script type="text/javascript">
function ajaxUpload() {
var form=new FormData();
//獲取選擇的文件
$.each($('input[name="files"]'),function (index,item) {
form.append("files",item.files[0])
});
//發送異步請求
$.ajax({
method:'post',
url:'/ajaxUploadFile',
data:form,
processData: false,
contentType:false,
success:function (res) {
//成功返回觸發的方法
alert(res.msg);
},
//請求失敗觸發的方法
error:function () {
console.log("ajax請求失敗");
}
})
}
</script>
</body>
</html>
後端代碼
//來到單文件上傳頁面(異步)
@GetMapping("/ajaxUpload")
public String ajaxUpload(){return "ajaxUpload";}
//文件上傳管理(異步)
@PostMapping("/ajaxUploadFile")
@ResponseBody
public Map ajaxUploadFile(MultipartFile[] files){
Map<String,Object> map=new HashMap<>();
for(MultipartFile file:files){
//獲取文件名以及後綴名
String fileName=file.getOriginalFilename();
//獲取jar包所在目錄
ApplicationHome h = new ApplicationHome(getClass());
File jarF = h.getSource();
//在jar包所在目錄下生成一個upload文件夾用來存儲上傳的圖片
String dirPath = jarF.getParentFile().toString()+"/upload/";
System.out.println(dirPath);
File filePath=new File(dirPath);
if(!filePath.exists()){
filePath.mkdirs();
}
try{
//將文件寫入磁盤
file.transferTo(new File(dirPath+fileName));
//文件上傳成功返回狀態信息
map.put("msg","上傳成功!");
}catch (Exception e){
e.printStackTrace();
//上傳失敗,返回失敗信息
map.put("msg","上傳失敗!");
}
}
//攜帶上傳狀態信息回調到文件上傳頁面
return map;
}
獲取圖片的方式參考(1)單文件上傳(非異步)
三、總結
(1)圖片不能存儲在項目裏面的靜態資源裏面
(2)圖片存儲的位置在jar包所在目錄,沒打jar包時是target下的目錄位置,打jar包後是jar所在目錄(動態)
(3)圖片存儲路徑的獲取用以下代碼,獲取的路徑是target的目錄
//獲取jar包所在目錄
ApplicationHome h = new ApplicationHome(getClass());
File jarF = h.getSource();
//在jar包所在目錄下生成一個upload文件夾用來存儲上傳的圖片
String dirPath = jarF.getParentFile().toString()+"/upload/";
System.out.println(dirPath);