1.1. 傳統項目中的圖片管理
傳統項目中,可以在web項目中添加一個文件夾,來存放上傳的圖片。例如在工程的根目錄WebRoot下創建一個images文件夾。把圖片存放在此文件夾中就可以直接使用在工程中引用。
優點:引用方便,便於管理
缺點:
1、如果是分布式環境圖片引用會出現問題。
2、圖片的下載會給服務器增加額外的壓力。
傳統圖片管理方式在分布式環境中的問題:
1.2. 分布式環境的圖片管理
分布式環境一般都有一個專門的圖片服務器存放圖片。
專門保存圖片,不管是哪個服務器接收到圖片,都把圖片上傳到圖片服務器。
圖片服務器上需要安裝一個http服務器,可以使用tomcat、nginx
我們使用虛擬機搭建一個專門的服務器來存放圖片。在此服務器上安裝一個nginx來提供http服務,安裝一個ftp服務器來提供圖片上傳服務。
1.3. 搭建圖片服務器
第一步:安裝vsftpd提供ftp服務(注意跟xftp不同,協議與端口都不同)
第二步:安裝nginx提供http服務
(這兩步請參見這兩個文檔http://files.cnblogs.com/files/xujingyang/Linux%E4%B8%8Bnginx%E5%92%8Cvsftpd%E5%AE%89%E8%A3%85%E6%89%8B%E5%86%8C.zip)
1.4. 測試圖片服務器
1. ftp服務測試。
a)使用ftp客戶端
b)使用java程序
ftp可以需要依賴commons-net-3.3.jar包。
1 package cn.xjy.test ; 2 3 import java.io.File ; 4 import java.io.FileInputStream ; 5 import org.apache.commons.net.ftp.FTP ; 6 import org.apache.commons.net.ftp.FTPClient ; 7 import org.junit.Test ; 8 9 public class TestFTP { 10 11 @Test 12 public void testFtp() throws Exception { 13 FTPClient ftpClient = new FTPClient() ; 14 ftpClient.connect("192.168.48.130") ; 15 ftpClient.login("ftpuser", "ftpuser"); 16 FileInputStream inputStream=new FileInputStream(new File("src/test/resources/test.txt")); 17 18 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); 19 ftpClient.storeFile("test.txt", inputStream); 20 inputStream.close(); 21 ftpClient.logout(); 22 } 23 }
2. ftp服務測試
a) 瀏覽器測試 (火狐)
1.5. SpringMVC中實現圖片上傳
上傳思路:
第一步:
導入common-fileupload的依賴
1 <!-- 文件上傳組件 --> 2 <dependency> 3 <groupId>commons-fileupload</groupId>, 4 <artifactId>commons-fileupload</artifactId> 5 </dependency>
第二步:
在SpringMVC配置文件中添加文件上傳解析器
1 <!-- 定義文件上傳解析器 --> 2 <bean id="multipartResolver" 3 class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 4 <!-- 設定默認編碼 --> 5 <property name="defaultEncoding" value="UTF-8"></property> 6 <!-- 設定文件上傳的最大值5MB,5*1024*1024 --> 7 <property name="maxUploadSize" value="5242880"></property> 8 </bean>
1.6. Service實現
1. 獲取資源配置文件的內容
第一步:
創建資源配置文件
1 #FTP地址 2 #FTP端口 3 FTP_ADDRESS=192.168.31.134 4 FTP_PORT=21 5 FTP_USERNAME=ftpuser 6 FTP_PASSWORD=ftpuser 7 FTP_BASE_PATH=/home/ftpuser/www 8 #顯示圖片使用的url 9 IMAGE_BASE_URL=http://192.168.31.134 10 11 #rpc協議使用的url 12 RPC_BASE_URL=http://127.0.0.1:8080/rpc 13 RPC_CONTENT_SYNC_URL=/cache/sync/content/
第二步:
在Spring(applicationContext-dao.xml)容器中加載資源文件
2. 圖片名生成策略
時間+隨機數:
1 package cn.xjy.utils ; 2 3 import java.util.Random ; 4 5 public class NameUtil { 6 7 /** 8 * 圖片名生成 9 */ 10 public static String genImageName() { 11 // 取當前時間的長整形值包含毫秒 12 long millis = System.currentTimeMillis() ; 13 // long millis = System.nanoTime(); 14 // 加上三位隨機數 15 Random random = new Random() ; 16 int end3 = random.nextInt(999) ; 17 // 如果不足三位前面補0 18 String str = millis + String.format("%03d", end3) ; 19 20 return str ; 21 } 22 23 }
或者使用uuid
3. Service實現

1 package cn.xjy.service ; 2 3 import java.util.Date ; 4 import org.springframework.beans.factory.annotation.Value ; 5 import org.springframework.stereotype.Service ; 6 import org.springframework.web.multipart.MultipartFile ; 7 import cn.xjy.bean.PictureResult ; 8 import cn.xjy.utils.FtpUtil ; 9 import cn.xjy.utils.NameUtil ; 10 11 @Service 12 public class PictureServiceImpl implements PictureService { 13 14 @Value("${IMAGE_BASE_URL}") 15 private String IMAGE_BASE_URL ; 16 @Value("${FTP_BASE_PATH}") 17 private String FTP_BASE_PATH ; 18 @Value("${FTP_ADDRESS}") 19 private String FTP_ADDRESS ; 20 @Value("${FTP_PORT}") 21 private Integer FTP_PORT ; 22 @Value("${FTP_USERNAME}") 23 private String FTP_USERNAME ; 24 @Value("${FTP_PASSWORD}") 25 private String FTP_PASSWORD ; 26 27 @Override 28 public PictureResult uploadFile(MultipartFile uploadFile) { 29 // 上傳文件功能實現 30 String path ; 31 try { 32 path = savePicture(uploadFile) ; 33 // 數據回顯 34 return new PictureResult(0, IMAGE_BASE_URL + path) ; 35 } catch (Exception e) { 36 e.printStackTrace() ; 37 } 38 return null ; 39 } 40 41 @Override 42 public String savePicture(MultipartFile uploadFile) throws Exception { 43 System.out.println("uploadFile"+uploadFile) ; 44 // 判斷文件是否為空,如果為空則返回 45 if (uploadFile.isEmpty()) { return null ; } 46 47 // 設置文件上傳的目錄,以日期為單位,提高訪問速度 48 String filePath = "/" + new Date().getYear() + "/" + new Date().getMonth() + "/" 49 + new Date().getDay() ; 50 System.out.println("filePath"+filePath) ; 51 // 獲取原始文件名 52 String originalFilename = uploadFile.getOriginalFilename() ; 53 System.out.println("originalFilename:"+originalFilename) ; 54 // 生成新文件名 55 String newFileName = NameUtil.genImageName() 56 + originalFilename.substring(originalFilename.lastIndexOf(".")) ; 57 System.out.println("newFileName"+newFileName) ; 58 // 上傳文件 59 boolean b = FtpUtil.uploadFile(FTP_ADDRESS, FTP_PORT, FTP_USERNAME, FTP_PASSWORD, 60 FTP_BASE_PATH, filePath, newFileName, uploadFile.getInputStream()) ; 61 System.out.println("上傳結果:"+b) ; 62 63 System.out.println("res"+filePath + "/" + newFileName) ; 64 65 return filePath + "/" + newFileName ; 66 67 } 68 }
4. Controller實現
1 package cn.xjy.controller ; 2 3 import org.springframework.beans.factory.annotation.Autowired ; 4 import org.springframework.stereotype.Controller ; 5 import org.springframework.web.bind.annotation.RequestMapping ; 6 import org.springframework.web.bind.annotation.ResponseBody ; 7 import org.springframework.web.multipart.MultipartFile ; 8 import cn.xjy.bean.PictureResult ; 9 import cn.xjy.service.PictureService ; 10 11 @Controller 12 @RequestMapping("/pic") 13 public class PictureController { 14 15 @Autowired 16 PictureService pictureService ; 17 18 @RequestMapping("/upload") 19 public @ResponseBody PictureResult upload(MultipartFile uploadFile) { 20 // 上傳圖片 21 PictureResult result = pictureService.uploadFile(uploadFile) ; 22 return result ; 23 } 24 }
Nginx找不到圖片問題:(原因:沒有加’user root;’配置,解決:在/usr/local/nginx/conf/nginx.conf 的首行加上 user root;) 步驟如下:
vi /usr/local/nginx/conf/nginx.conf
修改/usr/local/nginx/conf/nginx.conf 文件配置后,service nginx restart
注意:nginx.config中要配置root的指向為ftp的家目錄
vim /usr/local/nginx/conf/nginx.conf