javascript
springcloud 文件服务器,SpringCloud传文件
最近要做個需求: 手機app上傳視頻文件到服務器, 文件可能有幾百兆字節。 ?但目前尚沒有使用七牛等類似的文件服務器,要自己實現這個功能。 考慮方案:
1、單文件斷點續傳, 即只有1個線程使用multipart方式從客戶端上傳文件, 服務器每接收完一個part則保存到文件。 優點:實現比較簡單;
缺點:1、單線程慢, 由于傳輸時間長,傳輸中很可能中斷。
2、由于長時間阻塞服務器線程, 可能出現網絡擁塞情況。
2、切片上傳, 即將大文件分割成若干片在多線程并發上傳。 舉例: 待傳文件大小為201M字節, 按照每5M邏輯上切割為41段(其實就是從不同的位置開始傳,切片大則傳輸時間長且易失敗);假設使用5個線程并發上傳, 理論上比上一種方案減少了80%的上傳時間。
缺點:實現較復雜, 上傳的每段字節流在服務器上都是一個單獨的文件(邏輯上的中間文件), 服務器要判斷所有切片都上傳完成后做文件合并,并刪除切片文件; 服務器要做定時任務, 刪除長時間無效的中間文件。 如果一個切片上傳失敗則需要從頭再傳。
優點:上傳速度快,比上一個方案成功率高。
3、切片斷點續傳, 即將大文件視為由若干段小文件組成, 在上一個方案基礎上添加各個切片的斷點續傳功能。
缺點:實現最復雜, 每次上傳前要跟服務器同步一下各個切片的上傳狀態(即文件預期總大小、當前文件大小等), 以服務器為準。
優點:最快且省流量。
4、為了保證文件傳輸過程中的數據可靠性( 傳輸層有可能丟包 ),可以添加CRC校驗碼。 即客戶端計算所傳輸文件數據的校驗碼, 服務器接收到文件數據后計算校驗碼是否匹配。 如果不匹配,說明數據不完整, 需要客戶端重傳;如果匹配則走正常流程。
按照第2種方案的思路, 使用SpringCloud實現一個上傳文件服務。 新建一個AndroidStudio工程,配置pom.xml
SpringCloudFileSvr
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.5.9.RELEASE
UTF-8
UTF-8
1.8
Edgware.RELEASE
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-zuul
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
? ? ? ?其中的注冊中心、zuul網關在下面的demo中沒用到, 但實際項目中肯定要用。
為了測試方便寫個網頁, 注釋里已提醒name字段值使用在http包體的multipart中, 代碼里要用到這個值。 action值是在Controller類中配置的, 建議層級深一些,方便zuul路由和區分各個業務。
上傳文件請選擇文件:
修改application.yml, 添加multipart屬性。
server:
port: 9000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
spring:
application:
name: fileserver
http:
multipart:
max-file-size: 5Mb # Max file size
max-request-size: 5Mb # Max request size
新建controller類, 將文件存儲到服務器的一個目錄中。
@RestController
@RequestMapping(value = "/fileserver/pictures")
public class PictureController {
private final String CATEGORY_TEST = "pics";
@RequestMapping(value = "test")
@ResponseBody
public String testFileServer() {
return "文件服務器已啟動";
}
/**
* 上傳文件。
* @param file, 文件字節流, 其中filename是multipart中的變量名稱
* @return
*/
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public PictureResp uploadFile(/**HttpServletRequest request, 拿到請求的所有信息 */
//@RequestHeader(value = "Range") String range, //大文件分段上傳,格式: Range: start-end/total
@RequestHeader(value = "Content-Type") String type,
//@RequestParam(value = "signparam") String data, //在http包體里添加驗簽的json
@RequestParam(value = "filename", required = true)MultipartFile file) {
//System.out.println(request.getHeader("Content-Type")); //文件分片或斷點續傳需要Range頭,表示字節流對應原始文件的位置
System.out.println("請求類型:" + type);
PictureResp resp = new PictureResp();
try {
File dir = new File(CATEGORY_TEST);
if (!dir.exists()) {
dir.mkdirs(); //判斷并創建文件夾
}
byte[] bytes = file.getBytes(); //文件字節流
File fileToSave = new File(dir.getAbsolutePath() + File.separator + file.getOriginalFilename());
FileCopyUtils.copy(bytes, fileToSave); //保存文件
//數據表里要存儲原始文件名、用戶id、時間戳、服務器生成的文件名, 客戶端文件起始位置start、客戶端文件終止位置end、客戶端文件大小total等
resp.setStatus(0);
resp.setSize(fileToSave.length());
resp.setPath(fileToSave.getPath());
} catch (IOException ex) {
ex.printStackTrace();
resp.setStatus(1); //失敗
}
return resp;
}
}
運行服務并在瀏覽器中輸入: localhost:9000/index.html
選擇電腦里的文件(要小于5M)后,
點擊“上傳”按鈕后網頁會顯示結果
{"status":0,"size":135017,"index":0,"path":"/Users/***/AndroidStudioProjects/SpringCloudFileSvr/pics/jmeter.log"}
demo僅實現了單文件上傳功能, 后續應創建數據表存儲各個切片的信息, 用于合并文件或刪除過期中間文件時使用。
代碼:?http://download.csdn.net/download/brycegao321/10158457
總結
以上是生活随笔為你收集整理的springcloud 文件服务器,SpringCloud传文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql cluster proxy_
- 下一篇: 如何用php查不同,php-MySql调