帶有進(jìn)度條的fastdfs文件下載的demo,也有上傳,刪除文件的功能

通過fastdfs-java-client的api按塊下載文件,下載成功后寫入到輸出流并將進(jìn)度按用戶通過websocket推送到客戶端

注:該demo只是單純實(shí)現(xiàn)了有進(jìn)度條的下載,如果下載的接口不做其它處理用戶會(huì)卡在下載進(jìn)程里,后續(xù)再做處理

源碼git地址:https://github.com/xujun738/spring-uploadfile.git這里的代碼已經(jīng)在用戶請(qǐng)求后另起一個(gè)線程進(jìn)行下載處理

1.pom.xml

<!—fastdfs-client—>

<dependency>

?? <groupId>com.github.tobato</groupId>

?? <artifactId>fastdfs-client</artifactId>

?? <version>1.26.5</version>

</dependency>

<!—springboot ?websocket—>

<dependency>

?? <groupId>org.springframework.boot</groupId>

?? <artifactId>spring-boot-starter-websocket</artifactId>

</dependency>

springboot集成fastdfs

配置application.yml

fdfs:

? so-timeout: 600000

? connectTimeout: 600

? thumbImage:???????????? #縮略圖生成參數(shù)

??? width: 150

??? height: 150

? pool:

??? jmx-enabled: false

??? max-total: 200

??? max-wait-millis: 30000

? trackerList:??????????? #TrackerList參數(shù),支持多個(gè)

??? - ip:22122?? # 107.182.180.143:22122

? visit:

url:http://ip? #47.100.116.208

??? port: 8888

Websocket配置類

@Configuration

public class WebSocketConfig {

??? @Bean

??? public ServerEndpointExporter serverEndpointExporter() {

??????? return new ServerEndpointExporter();

??? }

}

websocket服務(wù)類

/**

* <p>Description : </p>

* <p>Copyright : Copyright (c) 2018</p>

* <p>Company : tgram </p>

*

* @author eric

* @version 1.0

* @Date 2019/3/8 上午9:57

*/

@ServerEndpoint("/websocket/{userId}")

@Component

public class MyWebSocket {

??? //靜態(tài)變量,用來記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計(jì)成線程安全的。

??? private static int onlineCount = 0;

??? //concurrent包的線程安全Set,用來存放每個(gè)客戶端對(duì)應(yīng)的MyWebSocket對(duì)象。

??? private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();

??? //與某個(gè)客戶端的連接會(huì)話,需要通過它來給客戶端發(fā)送數(shù)據(jù)

??? private Session session;

??? private String userId = null;

??? /**

???? * 連接建立成功調(diào)用的方法

???? */

??? @OnOpen

??? public void onOpen(Session session, @PathParam("userId") String userId) {

??????? this.session = session;

??????? this.userId = userId;

??????? webSocketSet.add(this);???? //加入set中

??????? addOnlineCount();?????????? //在線數(shù)加1

??????? System.out.println("有新連接加入!當(dāng)前在線人數(shù)為" + getOnlineCount());

??????? try {

??????????? sendMessage("連接成功");

??????? } catch (IOException e) {

??????????? System.out.println("IO異常");

??????? }

??? }

??? /**

???? * 連接關(guān)閉調(diào)用的方法

???? */

??? @OnClose

??? public void onClose() {

??????? webSocketSet.remove(this);? //從set中刪除

??????? subOnlineCount();?????????? //在線數(shù)減1

??????? System.out.println("有一連接關(guān)閉!當(dāng)前在線人數(shù)為" + getOnlineCount());

??? }

??? /**

???? * 收到客戶端消息后調(diào)用的方法

???? *

???? * @param message 客戶端發(fā)送過來的消息

???? */

??? @OnMessage

??? public void onMessage(String message, Session session) {

??????? System.out.println("來自客戶端的消息:" + message);

??????? //群發(fā)消息

??????? for (MyWebSocket item : webSocketSet) {

??????????? try {

??????????????? item.sendMessage(message);

??????????? } catch (IOException e) {

??????????????? e.printStackTrace();

??????????? }

??????? }

??? }

??? /**

???? * 發(fā)生錯(cuò)誤時(shí)調(diào)用

???? *

???? * @OnError public void onError(Session session, Throwable error) {

???? * System.out.println("發(fā)生錯(cuò)誤");

???? * error.printStackTrace();

???? * }

???? * <p>

???? * <p>

???? * public void sendMessage(String message) throws IOException {

???? * this.session.getBasicRemote().sendText(message);

???? * //this.session.getAsyncRemote().sendText(message);

???? * }

???? * <p>

???? * <p>

???? * /**

???? * 群發(fā)自定義消息

???? */

??? public static void sendInfo(String message, @PathParam("userId") String userId) throws IOException {

??????? for (MyWebSocket item : webSocketSet) {

??????????? try {

??????????????? //這里可以設(shè)定只推送給這個(gè)userId的,為null則全部推送

??????????????? if (userId == null) {

??????????????????? item.sendMessage(message);

??????????????? } else if (item.userId.equals(userId)) {

??????????????????? item.sendMessage(message);

??????????????? }

??????????? } catch (IOException e) {

??????????????? continue;

??????????? }

??????? }

??? }

??? /**

???? * 實(shí)現(xiàn)服務(wù)器主動(dòng)推送

???? */

??? public void sendMessage(String message) throws IOException {

??????? this.session.getBasicRemote().sendText(message);

??? }

??? public static synchronized int getOnlineCount() {

??????? return onlineCount;

??? }

??? public static synchronized void addOnlineCount() {

??????? MyWebSocket.onlineCount++;

??? }

??? public static synchronized void subOnlineCount() {

??????? MyWebSocket.onlineCount--;

??? }

}

5.控制層類

@Controller

@RequestMapping("/upload")

public class UploadCtrl {

??? @Autowired

??? private FastDFSClientWrapper fastDFSClientWrapper;

??? @Autowired

??? private FastFileStorageClient storageClient;

??? @RequestMapping(value = "", method = RequestMethod.POST)

??? @ResponseBody

??? public InfoMsg fileUpload(@RequestParam("uploadFile") MultipartFile file) {

??????? InfoMsg infoMsg = new InfoMsg();

??????? if (file.isEmpty()) {

??????????? infoMsg.setCode("error");

??????????? infoMsg.setMsg("Please select a file to upload");

??????????? return infoMsg;

??????? }

??????? try {

??????????? String url = fastDFSClientWrapper.uploadFile(file);

??????????? System.out.println("上傳的文件URL:?? " + url);

??????????? JSONObject jsonObject = new JSONObject();

??????????? jsonObject.put("url", url);

??????????? jsonObject.put("filesize", file.getSize());

//?????? File tmp = new File(TMP_PATH, file.getOriginalFilename());

//?????? if(!tmp.getParentFile().exists()){

//????????? tmp.getParentFile().mkdirs();

//?????? }

//?????? file.transferTo(tmp);

??????????? infoMsg.setCode("success");

??????????? infoMsg.setMsg("You successfully uploaded '" + file.getOriginalFilename() + "'");

??????? } catch (IOException e) {

??????????? infoMsg.setCode("error");

??????????? infoMsg.setMsg("Uploaded file failed");

??????? }

??????? return infoMsg;

??? }

??? @RequestMapping(value = "/delete", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")

??? @ResponseBody

??? public String deleteFile(String fileName) {

??????? try {

??????????? fastDFSClientWrapper.deleteFile(fileName);

??????????? return "刪除成功";

??????? } catch (Exception e) {

??????????? e.printStackTrace();

??????????? return "刪除失敗";

??????? }

??? }

??? @RequestMapping(value = "/download")

??? @ResponseBody

??? public void download(String fileName, HttpServletResponse response, String userId) throws IOException {

??????? StorePath storePath = StorePath.parseFromUrl(fileName);

??????? // 配置文件下載

??????? response.setHeader("content-type", "application/octet-stream");

??????? response.setContentType("application/octet-stream");

??????? // 下載文件能正常顯示中文

??????? response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

//??????? byte[] r = storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadCallback<byte[]>() {

//??????????? @Override

//??????????? public byte[] recv(InputStream ins) throws IOException {

//??????????????? byte[] reulst = IOUtils.toByteArray(ins);

//??????????????? System.out.println(reulst.length);

//??????????????? return reulst;

//??????????? }

//??????? });

//??????? response.getOutputStream().write(r);

??????? FileInfo fileInfo = storageClient.queryFileInfo(storePath.getGroup(), storePath.getPath());

??????? long fileSize = fileInfo.getFileSize();

??????? System.out.println("文件總大小:" + fileSize);

??????? long slice = Math.floorDiv(fileSize, 100);

??????? long left = fileSize - slice * 99;

??????? byte[] sliceBytes = null;

??????? int downloadBytes = 0;

??????? ByteBuffer bb = new ByteBuffer();

??????? for (int i = 0; i < 100; i++) {

??????????? if (i != 99) {

??????????????? sliceBytes = storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), i * slice, slice, ins -> {

??????????????????? byte[] result = IOUtils.toByteArray(ins);

??????????????????? response.getOutputStream().write(result);

??????????????????? return result;

??????????????? });

??????????? } else {

??????????????? sliceBytes = storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), 99 * slice, left, ins -> {

??????????????????? byte[] result = IOUtils.toByteArray(ins);

??????????????????? response.getOutputStream().write(result);

??????????????????? return result;

??????????????? });

??????????? }

??????????? downloadBytes = downloadBytes + sliceBytes.length;

??????????? MyWebSocket.sendInfo((i + 1) + "", userId);

??????? }

??????? response.getOutputStream().flush();

//??????? 新起一個(gè)線程,然后按段下載文件,每段下載成功后將進(jìn)度值推送到對(duì)應(yīng)的用戶

??????? System.out.println("共下載:" + downloadBytes);

??? }

}

服務(wù)啟動(dòng)類

@SpringBootApplication

@Import(FdfsClientConfig.class)

@EnableAutoConfiguration

public class StudyApplication {

?? public static void main(String[] args) {

????? new SpringApplication(StudyApplication.class).run(args);

?? }

}

7.html頁面

<!DOCTYPE HTML>

<html>

<head>

????<title>My WebSocket</title>

</head>

<body>

Welcome<br/>

<input id="text" type="text" /><button onclick="send()">Send</button>????<button onclick="closeWebSocket()">Close</button>

<div id="message">

</div>

</body>

<script type="text/javascript">

????var websocket = null;

????//判斷當(dāng)前瀏覽器是否支持WebSocket

????if('WebSocket' in window){

websocket = new WebSocket("ws://localhost:8080/websocket/admin1");

????}

????else{

????????alert('Not support websocket')

????}

????//連接發(fā)生錯(cuò)誤的回調(diào)方法

????websocket.onerror = function(){

????????setMessageInnerHTML("error");

????};

????//連接成功建立的回調(diào)方法

????websocket.onopen = function(event){

????????setMessageInnerHTML("open");

????}

????//接收到消息的回調(diào)方法

????websocket.onmessage = function(event){

????????setMessageInnerHTML(event.data);

????}

????//連接關(guān)閉的回調(diào)方法

????websocket.onclose = function(){

????????setMessageInnerHTML("close");

????}

????//監(jiān)聽窗口關(guān)閉事件,當(dāng)窗口關(guān)閉時(shí),主動(dòng)去關(guān)閉websocket連接,防止連接還沒斷開就關(guān)閉窗口,server端會(huì)拋異常。

????window.onbeforeunload = function(){

????????websocket.close();

????}

????//將消息顯示在網(wǎng)頁上

????function setMessageInnerHTML(innerHTML){

????????document.getElementById('message').innerHTML += innerHTML + '<br/>';

????}

????//關(guān)閉連接

????function closeWebSocket(){

????????websocket.close();

????}

????//發(fā)送消息

????function send(){

????????var message = document.getElementById('text').value;

????????websocket.send(message);

????}

</script>

</html>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JAVA面試題 1、作用域public,private,protected,以及不寫時(shí)的區(qū)別答:區(qū)別如下:作用域 ...
    JA尐白閱讀 1,261評(píng)論 1 0
  • 原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-WebSo...
    敢夢(mèng)敢當(dāng)閱讀 9,029評(píng)論 0 50
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 4,010評(píng)論 0 11
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡(jiǎn)單原理和應(yīng)用。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 5,182評(píng)論 1 114
  • 姓名:易平香 企業(yè)名稱:東莞耀升機(jī)電有限公司 組別:AT感謝組/272期努力一組 【日精進(jìn)打卡第70天】 【知~學(xué)...
    shine1yi閱讀 190評(píng)論 0 0

友情鏈接更多精彩內(nèi)容