1. 程式人生 > >FastDFS+MultipartFile+angularJS檔案上傳

FastDFS+MultipartFile+angularJS檔案上傳

總結一個檔案上傳的案例,使用到的主要技術有:

1. angularJS檔案上傳, 2. Spring MVC 多媒體解析器元件:CommonsMultipartResolver, 3. FastDFS分散式檔案系統。

1.FastDFS分散式檔案系統

概述

百度百科:一個開源的輕量級分散式檔案系統,FastDFS為網際網路量身定製,充分考慮了冗餘備份、負載均衡、線性擴容等機制,並注重高可用、高效能等指標,使用FastDFS很容易搭建一套高效能的檔案伺服器叢集提供檔案上傳、下載等服務。 用來儲存檔案的伺服器,是用c語言編寫的,我們看一下它的系統架構: 在這裡插入圖片描述 簡單介紹一下:FastDFS 服務端包括 Tracker server 和 Storage server。客戶端請求 Tracker server 進行檔案上傳、下載,通過 Tracker server 排程最終由 Storage server 完成檔案上傳和下載。 Tracker server 是用來管理排程Storage群的 ,Storage會定時向Tracker server傳送報告(心跳檢查),如果哪個沒有傳送,Tracker會認為這個Storage已經宕機,不會再呼叫它。所以實現了高可用性。 Storage也是一個分散式+叢集的架構,所以訪問時,要通過nginx反向代理訪問。

檔案上傳流程 在這裡插入圖片描述 客戶端上傳檔案後儲存伺服器將檔案 ID 返回給客戶端,此檔案 ID 用於以後訪問該檔案的索引資訊。

java客戶端使用:

FastDFS 的安裝一般是由運維工程師完成的,我們開發人員需要知道其ip地址。 寫一個上傳檔案的demo: 1.匯入依賴

	<dependency>
	    <groupId>org.csource.fastdfs</groupId>
	    <artifactId>fastdfs</artifactId>
	    <version>1.2</version>
	</dependency>

這個jar中央倉庫沒有,我們要自己上傳到本地倉庫 2.配置檔案:

connect_timeout = 2
network_timeout = 30
charset = ISO8859-1
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key = FastDFS1234567890

tracker_server = IP地址:22122

將我們的FastDFS伺服器ip地址填寫進去,這個配置檔案哪來的,安裝好FastDFS後,它自帶有一些啟動指令碼及配置檔案,這個配置檔案的目錄是/etc/fdfs/client.conf(把註釋去掉就找這個樣子)。 3.程式碼

public class FastDFSDemo {
    public static void main(String[] args) throws Exception {
        //載入配置檔案
        ClientGlobal.init("D:\\IdeaProjects\\fastdfs-demo2\\src\\fdfs_client.conf");
        
        //建立TrackerClient,呼叫方法建立TrackerServer
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        
        //建立StorageClient,第二個引數是StorageServer我們這裡有全域性變數初始化ClientGlobal.init,會幫我們去找伺服器?(自己想的)
        StorageClient storageClient = new StorageClient(trackerServer, null);
        
        //呼叫方法上傳檔案
        String[] strings = storageClient.upload_file("E:\\picture\\lin.jpg", "jpg", null);
        
        //檢視返回的fileID,兩個元素,第一個是組名,第二個是檔名
        for (String string : strings) {
            System.out.println(string);
        }
    }
}

4.控制檯:

group1
M00/00/00/wKgZhVkMP4KAZEy-AAA-tCf93Fo973.jpg

fileId包括:組名,虛擬磁碟路徑,資料兩級目錄,檔名。建立StorageClient時我們可以建立fastdfs提供的另一個api: StorageClient1,其有一個上傳方法是 String upload_file1(TrackerServer trackerServer, StorageServer storageServer), 可以直接返回組名+檔案的全FileId。

2. Spring MVC 檔案上傳

前端: 檔案上傳表單要求滿足三點要求: 1.表單的enctype屬性的值設定為multipart/form-data 2.表單要有type=file檔案上傳輸入框 3.表單的請求方式必須是post

 <form action="file/springmvcFileUpload" method="post" enctype="multipart/form-data">
        <input type="file" name="upload"/>
        <input type="submit" value="上傳">
 </form>

後端: 在springmvc配置檔案中配置多媒體檔案解析器:CommonsMultipartResolver(Spring MVC 提供的解析檔案的元件),它可以自動解析multipart格式的資料,multipart是一個用隨機字串分割資料內容的資料格式(大概就這樣,下面說angularJS有),所以解析器可以獲得檔名,格式,二進位制資料等內容。

<!--id必須為multipartResolver,且必須寫-->
<bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"></property>
        <!-- 設定檔案上傳的最大值 5MB,5*1024*1024 -->
        <property name="maxUploadSize" value="5242880"></property>
 </bean>

在對應的上傳方法宣告上定義引數MultipartFile file,springmvc會幫我們把上傳的檔案的封裝到者file物件中:

@RestController
public class UploadController {

    @Value("${FILE_SERVER_URL}")
    private String FILE_SERVER_URL;

    @RequestMapping("/upload")
    public Result upload(MultipartFile file){

        try {
            //獲取副檔名
            String name = file.getOriginalFilename();
            int index = name.lastIndexOf(".");
            String extName = name.substring(index + 1);
            //上傳檔案,配置檔案就是上面說的那個
            FastDFSClient fastDFSClient = new FastDFSClient("classpath:config/fdfs_client.conf");
            String path = fastDFSClient.uploadFile(file.getBytes(), extName);
            //拼接資源路徑
            String url = FILE_SERVER_URL + path;
            return new Result(true,url);
        }catch (Exception e){
            e.printStackTrace();
            return new Result(false, "上傳失敗");
        }
    }
}

FastDFSClient工具類:(可以略過,就是上面FastDFS的java客戶端上傳檔案程式碼的封裝)

public class FastDFSClient {

	private TrackerClient trackerClient = null;
	private TrackerServer trackerServer = null;
	private StorageServer storageServer = null;
	private StorageClient1 storageClient = null;
	
	public FastDFSClient(String conf) throws Exception {
		if (conf.contains("classpath:")) {
			conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
			System.out.println(conf);
	}
		ClientGlobal.init(conf);
		trackerClient = new TrackerClient();
		trackerServer = trackerClient.getConnection();
		storageServer = null;
		storageClient = new StorageClient1(trackerServer, storageServer);
	}
	
	/**
	 * 上傳檔案方法
	 * <p>Title: uploadFile</p>
	 * <p>Description: </p>
	 * @param fileName 檔案全路徑
	 * @param extName 副檔名,不包含(.)
	 * @param metas 檔案擴充套件資訊
	 * @return
	 * @throws Exception
	 */
	public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
		String result = storageClient.upload_file1(fileName, extName, metas);
		return result;
	}
	
	public String uploadFile(String fileName) throws Exception {
		return uploadFile(fileName, null, null);
	}
	
	public String uploadFile(String fileName, String extName) throws Exception {
		return uploadFile(fileName, extName, null);
	}
	
	/**
	 * 上傳檔案方法
	 * <p>Title: uploadFile</p>
	 * <p>Description: </p>
	 * @param fileContent 檔案的內容,位元組陣列
	 * @param extName 副檔名
	 * @param metas 檔案擴充套件資訊
	 * @return
	 * @throws Exception
	 */
	public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
		
		String result = storageClient.upload_file1(fileContent, extName, metas);
		return result;
	}
	
	public String uploadFile(byte[] fileContent) throws Exception {
		return uploadFile(fileContent, null, null);
	}
	
	public String uploadFile(byte[] fileContent, String extName) throws Exception {
		return uploadFile(fileContent, extName, null);
	}
}

3.angularJS檔案上傳

angularJS是面向變數的JS框架,模組,MVC,依賴注入,雙向繫結四大特性,尤其是雙向繫結的思想,很牛逼,感嘆一下計算機語言前輩,大牛思想的偉大,堪比人類語言好嘛,折射事件萬物。 有時間寫一下angularJS框架的筆記。今天先說檔案上傳:

定義檔案上傳服務

app.service("uploadService",function ($http) {

    this.uploadFile=function () {
    
    //FormData是html5提供給我們的能夠承載二進位制資料的物件
        var formData = new FormData();
        //file.files[0]代表獲取name或id為file的輸入框中的第一個輸入框中內容
        formData.append("file",file.files[0]);
        
	//檔案上傳必須用這種原始請求方式,因為要設定headers
        return $http({
            method:"post",
            url:"../upload.do",
            data:formData,
            //這兩屬性下面說
            headers:{"Content-Type":undefined},
            transformRequest: angular.identity
        })
    }
});

anjularjs對於post和get請求預設的Content-Type header 是application/json。通過設定‘Content-Type’: undefined,這樣瀏覽器會幫我們把Content-Type 設定為 multipart/form-data. 通過設定 transformRequest: angular.identity ,anjularjs transformRequest function 將序列化我們的formdata object

在controller中引入檔案上傳服務,並定義函式:

  $scope.uploadFile=function(){	  
		uploadService.uploadFile().success(function(response) {        	
        	if(response.success){//如果上傳成功,取出url
        		$scope.image_entity.url=response.message;//設定檔案地址
        	}else{
        		alert(response.message);
        	}
        }).error(function() {           
        	     alert("上傳發生錯誤");
        });        
    };  

ok,看一下上傳的資料:

-----------------------------41184676334
Content-Disposition: form-data; name="file"; filename="ba017682d056f983b8f1656fcbfd5af5.jpg"
Content-Type: image/jpeg

›>ȉl”À\FþðM~PŽ=¦ö»š^Pó(sŽÓéIý♸›{ÝFºÝÁ3²¤{ÜXiÂáû¿@Â֐֞¾ÝOÙS—"Àdclc§ÏÉO†BÐC,8Š'¹ÿ
...二進位制資料

emm…完了把!