基于websocket 文件断点上传

阅读更多

对于打文件上传如果网突然断了,得重新来一遍,是不是很郁闷,怎么办,如果浏览器不支持FileAPI 那就只能使用 Flash来做断点上传,有了HTML5 基于Ajax或者WebSocket 的原生实现也很棒。

下面就是基于websocket  + spring 的一个实现例子 

 好了直接上代码

 

   

        文件上传

       

       

       

       

       

       

   

   

       

       

       

       

       

       

           

用户注册

           

               

                   

                   

                       

                   

               

               

                   

                   

                       

                   

               

               

                   

                   

                       

                   

               

               

                   

                   

                       

                   

               

               

                   

                   

                       

                       

                   

               

               

                   

                   

                       

                       

                   

               

               

                   

                   

                       

                   

               

               

                   

                       

                           

                                Remember me

                           

                       

                   

               

               

                   

                       

                   

               

 

           

       

 

       

            Image preview

            

           

       

       

           

       

   

 

spring 配置

   

       

       

           

       

   

   

   

       

       

   

 

FileUploadSocketHandler

 

import com.chameleon.document.DocumentBusiness;

import com.chameleon.document.model.File;

import com.chameleon.document.model.FileDiskContent;

import com.chameleon.document.model.FileUploadState;

import com.chameleon.util.Sequence;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.FileOutputStream;

import java.io.OutputStream;

import java.nio.ByteBuffer;

import java.text.DecimalFormat;

import java.util.HashMap;

import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.web.socket.BinaryMessage;

import org.springframework.web.socket.CloseStatus;

import org.springframework.web.socket.TextMessage;

import org.springframework.web.socket.WebSocketSession;

import org.springframework.web.socket.handler.AbstractWebSocketHandler;

/**

 *

 * @author Johnson.zhang

 */

public class FileUploadSocketHandler extends AbstractWebSocketHandler {

 

    private static final Logger logger = LoggerFactory.getLogger(FileUploadSocketHandler.class);

    private Map result = null;

    @Resource(name = "documentBusinessImpl")

    private DocumentBusiness documentBusiness;

    private ObjectMapper objectMapper = new ObjectMapper();

    private OutputStream outputStream;

    private long fileTotalSize;

    private long fileLoadSize;

    private DecimalFormat percentFormat = new DecimalFormat("0");

    private FileDiskContent fileDiskContent = null;

    @Resource(name = "systemFileUploadPath")

    private String uploadFilePath;

    @Resource(name = "sequenceSerialNumberImpl")

    private Sequence sequence;

 

    public void setUploadFilePath(String uploadFilePath) {

        this.uploadFilePath = uploadFilePath;

    }

 

    public void setObjectMapper(ObjectMapper objectMapper) {

        this.objectMapper = objectMapper;

    }

 

    public void setSequence(Sequence sequence) {

        this.sequence = sequence;

    }

 

    @Override

    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        String id = session.getId();

        logger.debug("WebSocket连接已经建立,连接ID为:" + id);

    }

 

    @Override

    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

        result = new HashMap();

        result.put("buffer", 8192);

        fileTotalSize = 0l;

        fileLoadSize = 0l;

        

        String msg = message.getPayload();

        fileDiskContent = objectMapper.readValue(msg, FileDiskContent.class);

        if (fileDiskContent.getId() != null && !fileDiskContent.getId().isEmpty()) {

            //续传文件

            CloseStatus status = null;

            String filePath = fileDiskContent.getPath();

            if (filePath == null || filePath.isEmpty()) {

                status = new CloseStatus(2001, "续传文件路径不能为空!");

            }

            java.io.File tempFile = new java.io.File(uploadFilePath + "/" + filePath);

            if (!tempFile.exists()) {

                status = new CloseStatus(2002, "续传文件不存在!");

            }

            if (!tempFile.isFile()) {

                status = new CloseStatus(2002, "续传文件不能是文件夹!");

            }

            if (status != null) {

                session.close(status);

                String rs = objectMapper.writeValueAsString(status);

                logger.debug("WebSocket 文件断点续传初始化发生错误: " + rs);

                return;

            }

            outputStream = new FileOutputStream(uploadFilePath + "/" + filePath, true);

            fileTotalSize = fileDiskContent.getSize();

            fileLoadSize = tempFile.length();

            if (fileTotalSize > 0) {

                double percent = ((double) fileLoadSize) / fileTotalSize * 100;

                result.put("percent", percentFormat.format(percent));

            }

            result.put("id", fileDiskContent.getId());

            result.put("name", fileDiskContent.getName());

            result.put("total", fileDiskContent.getSize());

            result.put("path", filePath);

            result.put("load", fileLoadSize);

            logger.debug("WebSocket 文件上传信息为: " + msg);

        } else {

            //新上传文件

            String filePath = sequence.getId();

            String tempPath = uploadFilePath + "/" + filePath;

            outputStream = new FileOutputStream(tempPath);

            fileDiskContent.setPath(filePath);

            fileDiskContent.setId(sequence.getId());

            fileTotalSize = fileDiskContent.getSize();

            

            result.put("id", fileDiskContent.getId());

            result.put("name", fileDiskContent.getName());

            result.put("total", fileDiskContent.getSize());

            result.put("path", filePath);

            result.put("load", fileLoadSize);

            result.put("percent", "0");

            logger.debug("WebSocket 文件上传信息为: " + msg);

            logger.debug("WebSocket 文件保存路径为: " + tempPath);

        }

        String rs = objectMapper.writeValueAsString(result);

        session.sendMessage(new TextMessage(rs));

    }

 

    @Override

    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {

        ByteBuffer msg = message.getPayload();

        byte[] buffer = msg.array();

        outputStream.write(buffer);

        fileLoadSize = fileLoadSize + buffer.length;

        logger.debug("WebSocket 文件已经上传了 [ " + fileLoadSize + " ] 字节");

        result.put("load", fileLoadSize);

        if (fileTotalSize > 0) {

            double percent = ((double) fileLoadSize) / fileTotalSize * 100;

            result.put("percent", percentFormat.format(percent));

        }

        if (fileLoadSize == fileTotalSize) {

            closeStream();

            if (fileDiskContent != null) {

                if (fileDiskContent.getMeta() == null) {

                    documentBusiness.saveFile(fileDiskContent);

                } else {

                    documentBusiness.deleteFileUploadStateByFile(fileDiskContent);

                }

            }

            logger.debug("WebSocket 文件已经保存到磁盘:【" + uploadFilePath + "/" + fileDiskContent.getPath() + "】");

            logger.debug("WebSocket 文件信息已经保存到数据库 文件ID为:【" + fileDiskContent.getId() + "】");

        }

        String rs = objectMapper.writeValueAsString(result);

        logger.debug("WebSocket 文件上传回显数据位 :【" + rs + "】");

        session.sendMessage(new TextMessage(rs));

    }

 

    @Override

    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

        String rs = objectMapper.writeValueAsString(exception);

        if (session.isOpen()) {

            session.sendMessage(new TextMessage(rs));

        }

        logger.debug("WebSocket 程序发生异常 :【" + rs + "】");

    }

 

    @Override

    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {

        closeStream();

        saveFileUploadState();

        String rs = objectMapper.writeValueAsString(status);

        logger.debug("WebSocket 连接关闭 :【" + rs + "】");

    }

 

    private void closeStream() throws Exception {

        if (outputStream != null) {

            outputStream.close();

            outputStream = null;

        }

    }

 

    private void saveFileUploadState() {

        if (fileLoadSize < fileTotalSize) {

            if (fileDiskContent.getMeta() == null) {

                FileUploadState fileUploadState = new FileUploadState();

                fileUploadState.setId(sequence.getId());

                fileUploadState.setLoadedSize(fileLoadSize);

                fileUploadState.setFile(fileDiskContent);

                documentBusiness.saveFileUploadState(fileUploadState);

            } else {

                documentBusiness.updateFileUploadStateByFile(fileDiskContent, fileLoadSize);

            }

        }

    }

}

 

你可能感兴趣的:(websocket,文件上传,断点续传)