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…完了把!