實現圖片上傳
剛纔的新增實現中,我們並沒有上傳圖片,接下來我們一起完成圖片上傳邏輯。
文件的上傳並不只是在品牌管理中有需求,以後的其它服務也可能需要,因此我們創建一個獨立的微服務,專門處理各種上傳。
搭建項目
- 創建微服務module
- EurekaClient和web依賴
- 編寫yml配置,注意限制文件上傳的大小
- 引導類
編寫上傳功能
controller
編寫controller需要知道4個內容:結合用法指南
-
請求方式:上傳肯定是POST
-
請求路徑:/upload/image
-
請求參數:文件,參數名是file,SpringMVC會封裝爲一個接口:MultipartFile
-
返回結果:上傳成功後得到的文件的url路徑,也就是返回String
代碼如下:
@Controller
@RequestMapping("upload")
public class UploadController {
@Autowired
private UploadService uploadService;
/**
* 圖片上傳
* @param file
* @return
*/
@PostMapping("image")
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file){
String url = this.uploadService.upload(file);
if (StringUtils.isBlank(url)) {
return ResponseEntity.badRequest().build();
}
return ResponseEntity.status(HttpStatus.CREATED).body(url);
}
}
service
在上傳文件過程中,我們需要對上傳的內容進行校驗:
-
校驗文件大小
-
校驗文件的媒體類型
-
校驗文件的內容
文件大小在Spring的配置文件中設置,因此已經會被校驗,我們不用管。
具體代碼:
@Service
public class UploadService {
private static final List<String> CONTENT_TYPES = Arrays.asList("image/jpeg", "image/gif");
private static final Logger LOGGER = LoggerFactory.getLogger(UploadService.class);
public String upload(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
// 校驗文件的類型
String contentType = file.getContentType();
if (!CONTENT_TYPES.contains(contentType)){
// 文件類型不合法,直接返回null
LOGGER.info("文件類型不合法:{}", originalFilename);
return null;
}
try {
// 校驗文件的內容
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
if (bufferedImage == null){
LOGGER.info("文件內容不合法:{}", originalFilename);
return null;
}
// 保存到服務器
file.transferTo(new File("C:\\leyou\\images\\" + originalFilename));
// 生成url地址,返回
return "http://image.leyou.com/" + originalFilename;
} catch (IOException e) {
LOGGER.info("服務器內部錯誤:{}", originalFilename);
e.printStackTrace();
}
return null;
}
}
這裏有一個問題:爲什麼圖片地址需要使用另外的url?
-
圖片不能保存在服務器內部,這樣會對服務器產生額外的加載負擔
-
一般靜態資源都應該使用獨立域名,這樣訪問靜態資源時不會攜帶一些不必要的cookie,減小請求的數據量
測試上傳
我們通過RestClient工具來測試:
繞過網關
圖片上傳是文件的傳輸,如果也經過Zuul網關的代理,文件就會經過多次網路傳輸,造成不必要的網絡負擔。在高併發時,可能導致網絡阻塞,Zuul網關不可用。這樣我們的整個系統就癱瘓了。
所以,我們上傳文件的請求就不經過網關來處理了。
Nginx的rewrite指令
server {
listen 80;
server_name api.leyou.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 上傳路徑的映射
location /api/upload {
proxy_pass http://127.0.0.1:8082;
proxy_connect_timeout 600;
proxy_read_timeout 600;
rewrite "^/api/(.*)$" /$1 break;
}
location / {
proxy_pass http://127.0.0.1:10010;
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}