最近在作一個基於Flutter的app,算是學習新的移動端開發技術。因而就須要一個後端api接口,其中涉及到了文件上傳,特此記錄下
原本我計劃的是,後臺只作數據接口,不作文件存儲,畢竟本身也沒那麼多的服務器資源去存儲。當時想的是用免費的第三方雲存儲解決方案,畢竟以前已經用過了七牛雲。javascript
可是問題來了,免費的雲存儲,總是出問題。好比七牛的,過段時間就會發現,外鏈訪問文件會失效,並且後臺文件管理面板,察看文件也看不了,很坑。html
而後又看了有拍雲,和騰訊雲,它們提供的文件存儲都不收費,可是要後收費,當你的文件存儲超過容量時收費。這也還好,畢竟免費的,存儲圖片的話5g也夠用了,可是主要是天天的流量由限制,超出流量收費。你後期不得面臨你的應用中的圖片所有不顯示,做爲定位上線的應用,是不能接受這種風險的。前端
因此你若是本身玩,徹底可使用免費的雲存儲,要是真的商用,就考慮付費產品。可是我又窮,因此只能本身寫了。java
就不貼所有的項目代碼了,只貼上傳部分的。由於使用了靜態資源訪問,因此須要加入模板引擎依賴。jquery
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
由於代碼比較簡單,因此直接controller所有處理完:web
package com.mike.controller; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.mike.bean.ApiResult; import com.mike.bean.FileView; import com.mike.util.ApiUtils; import com.mike.util.Tools; /** * The class UploadController */ @RestController @RequestMapping("/up") public class UploadController { @Value("${baseUrl}") private String baaseUrl; @CrossOrigin @PostMapping("/upload") public ApiResult uploadFile(@RequestParam("file") MultipartFile file){ if (file.isEmpty()) { return ApiUtils.err("你沒有選擇上傳文件"); } else if(file.getOriginalFilename().contains("..")||!file.getOriginalFilename().contains(".")){ return ApiUtils.err("文件格式有誤"); } else { String fileName = file.getOriginalFilename(); //爲防止文件名重複覆蓋 fileName = fileName.replace(".", System.currentTimeMillis()+"."); Path savePath = Paths.get("src/main/resources/static/upload"); try { Files.copy(file.getInputStream(), savePath.resolve(fileName), StandardCopyOption.REPLACE_EXISTING); FileView view = new FileView(); view.setName(fileName); view.setSize(file.getSize()); view.setUrl(baaseUrl+fileName); view.setUploadDate(Tools.getCurrent()); return ApiUtils.success(view); } catch (IOException e) { e.printStackTrace(); return ApiUtils.err("對不起,上傳失敗"); } } } }
在高併發下,仍是有很是小的概率出現文件重名,因此使用時間戳也不是好的解決方案。須要可以生成惟一識別符號,建議使用UUId。ajax
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <input type="file" id="file"> <button type="button" onclick="up()" name="上傳">上傳</button> <script src="https://cdnjs.cloudflare.com/ajax/libs/zui/1.8.1/lib/jquery/jquery.js"></script> <script type="text/javascript"> function up(){ var formData = new FormData(); formData.append("file", $("#file")[0].files[0]); console.log(formData); $.ajax({ type:'POST', url:"http://localhost:8080/up/upload", data:formData, contentType:false, processData:false,//這個頗有必要,否則不行 dataType:"json", mimeType:"multipart/form-data", success:function(data){ if("00"==data.code){ console.log(data.data); }else{ console.log("error"); } } }); } </script> </body> </html>
效果:spring
訪問上傳後的圖片url:json
由於圖片上傳導了代碼目錄,不是服務器的目錄,因此,新上傳得圖片訪問會報404,須要重起才能訪問。爲了解決這個問題,咱們須要增長文件與路徑的映射關係,這樣,就不會出現404後端
public class FileConfig implements WebMvcConfigurer { @Value("${serverFilePath}") private String serverFilePath; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { WebMvcConfigurer.super.addResourceHandlers(registry); registry.addResourceHandler("/upload/**") .addResourceLocations(serverFilePath); } }
serverFilePath 在properties中配置:
baseUrl=http://localhost:8080/upload/ serverFilePath=file:C:/code/mike-todo/src/main/resources/static/upload/
上線的話,換成服務器上的路徑就好。
文件存儲,遠遠不像我寫的這麼簡單。只是應付通常小項目足夠了,若是是大型的項目,就須要專門的文件存儲系統以及服務器端的優化。若是你有什麼問題,能夠留言要論。或是關注個人公衆號:mike啥都想搞
,還有其餘教學視頻免費領取。