1. 程式人生 > >大檔案資料分片上傳簡單示例

大檔案資料分片上傳簡單示例

文章目錄


大檔案資料分片上傳簡單示例

1. HTML

<input type="file" name="file" id="file">
<input type="button" id="uploadSlice"
value="檔案分片上傳">

2. JS

<script
        src="http://code.jquery.com/jquery-3.3.1.js"
        integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
        crossorigin="anonymous"></script>

<script>
    $("#uploadSlice").on("click", function () {
        uploadFile();
    }
); //分成多少片 var sliceSize; var timer; function uploadFile() { var file = $("#file")[0].files[0]; //檔案物件 if (file == undefined) { alert("請先選中檔案"); return; } if (file.size > 1024 * 1024 * 1024 * 2) { alert("檔案不能大於2GB"); return
; } var sliceLength = 1024 * 1024 * 100; //每片大小 sliceSize = Math.ceil(file.size / sliceLength); for (var i = 1; i <= sliceSize; i++) { var fileTmp; //最後一片 if (i == sliceSize) { fileTmp = file.slice(sliceLength * (i - 1), file.size + 1); } else { fileTmp = file.slice(sliceLength * (i - 1), sliceLength * i); } uploadSlice(fileTmp, file, i); if (i == 1) { uploadSchedule(); } } } function uploadSlice(formData, file, index) { var form = new FormData(); form.append("fileSize", file.size); form.append("sliceSize", sliceSize); form.append("index", index); form.append("file", formData); form.append("fileName", file.name); console.log("準備上傳第[" + index + "]個檔案"); $.ajax({ url: 'uploadSlice', data: form, type: 'post', async: true, processData: false, contentType: false, success: function (data) { console.log("code:" + data.code) if (data.code == 200) { console.log("上傳第[" + index + "]個檔案成功"); } }, error: function (data) { console.log(data.code + "上傳第[" + index + "]個檔案發生錯誤" + data.msg + ",錯誤原因:"); console.log(data); } }); } function uploadSchedule() { timer = setInterval(function () { $.ajax({ url: 'uploadSchedule', type: 'post', success: function (data) { if (data.data == null) { console.log(data); } if (data.data != null) { console.log(data.data); } if (data.code == 200) { console.log("進入清除定時器"); window.clearInterval(timer); } }, error: function (data) { console.log(data); } }); }, 1000); } </script>

3. Java

3.1 檔案屬性實體類

/**
 * @program: service-center
 * @description: 檔案Model,前端將檔案切片後將資料分片傳給後臺
 * @author: Mr.superbeyone
 * @create: 2018-11-14 09:20
 **/
public class FileModel {

    private int fileSize; //檔案大小

    private int sliceSize;  //切片數量

    private String md5;     //檔案md5值

    private int index;      //當前為第幾片

    private String fileName;   //檔名

    private MultipartFile file;     //檔案

	//GET SET
}

3.2 統一返回結果定義

/**
 * @program: 
 * @description:
 * @author: Mr.superbeyone
 * @create: 2018-10-18 16:37
 **/
public class JsonResult<T> {

    private Integer code;

    private String msg;

    private T data;

   //Get 
   //Set
}

3.3 Controller

@RestController
public class FileUploadController {

	@Autowired
    FileUploadService fileUploadService;

 	/**
     * 資料分片上傳
     *
     * @param fileModel
     * @return
     */
    @RequestMapping("/uploadSlice")
    public JsonResult<Object> uploadSlice(FileModel fileModel) {

        Object uploadSchedule = RequestHolder.getCurrentRequest().getSession().getAttribute("uploadSchedule");
        if (uploadSchedule == null) {
            RequestHolder.getCurrentRequest().getSession().setAttribute("uploadSchedule", new FileOperatorSchedule());
        }
        JsonResult<Object> jsonResult = fileUploadService.uploadFileSlice(fileModel);
        return jsonResult;
    }

	/**
     * 獲取上傳任務進度
     *
     * @return
     */
    @RequestMapping("/uploadSchedule")
    public JsonResult<FileOperatorSchedule> getUploadSchedule(HttpServletRequest request) {
        JsonResult<FileOperatorSchedule> result = new JsonResult<>();
        Object uploadSchedule = request.getSession().getAttribute("uploadSchedule");
        FileOperatorSchedule fileOperatorSchedule = null;
        if (uploadSchedule != null) {
            fileOperatorSchedule = (FileOperatorSchedule) uploadSchedule;

            if (fileOperatorSchedule.getFileSize() <= fileOperatorSchedule.getCompletedSize()) {

                result.setCode(200);
                result.setMsg("上傳任務完成");
                RequestHolder.getCurrentRequest().getSession().removeAttribute("uploadSchedule");
            } else {
                result.setCode(600);
                result.setMsg("上傳任務進行中");
            }
        } else {
            result.setCode(900);
            result.setMsg("資料準備中");
        }

        result.setData(fileOperatorSchedule);

        return result;
    }

}

3.4 Service實現類

/**
 * @program: service-center
 * @description:
 * @author: Mr.superbeyone
 * @create: 2018-10-19 12:54
 **/
@Service
public class FileUploadServiceImpl implements FileUploadService {
	 /**
     * 切片上傳檔案
     *
     * @param fileModel
     * @return
     */
    @Override
    public JsonResult<Object> uploadFileSlice(FileModel fileModel) {
        JsonResult<Object> result = new JsonResult<>();
        //檔案儲存的父資料夾位置
        File parentFolder = new File("D:\\data" + File.separator + fileModel.getFileName().substring(0, fileModel.getFileName().lastIndexOf(".")));
        if (!parentFolder.exists()) {
            parentFolder.mkdirs();
        }

        //檔案分片位置
        File file = null;
        if (fileModel.getSliceSize() == 1) {
            file = new File(parentFolder, fileModel.getFileName());
        } else {

            file = new File(parentFolder, fileModel.getFileName() + "_" + fileModel.getIndex());
        }
        if (file.exists()) {
            file.delete();
        }
        FileOperatorSchedule fileOperatorSchedule = (FileOperatorSchedule) RequestHolder.getCurrentRequest().getSession().getAttribute("uploadSchedule");
        if (fileOperatorSchedule == null) {
            fileOperatorSchedule = new FileOperatorSchedule();
        }
        fileOperatorSchedule.setFileSize(fileModel.getFileSize());

        BufferedOutputStream bufferedOutputStream = null;
        BufferedInputStream bufferedInputStream = null;
        try {
            //上傳檔案 1
//            fileModel.getFile().transferTo(file);

			//上傳檔案 2
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
            bufferedInputStream = new BufferedInputStream(fileModel.getFile().getInputStream());
            int len = 0;
            byte[] bytes = new byte[2048];


            while ((len = bufferedInputStream.read(bytes)) != -1) {
                bufferedOutputStream.write(bytes, 0, len);          
            }


            //判斷所有分片是否上傳完成,完成則合併
            File[] files = parentFolder.listFiles();
            if (files.length == fileModel.getSliceSize()) {   //上傳完成
                if (fileModel.getSliceSize() > 1) {
                    File newFile = new File(parentFolder, fileModel.getFileName());
                    bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newFile, true));
                    for (int i = 1; i <= files.length; i++) {
                        bufferedInputStream = new BufferedInputStream(new FileInputStream(new File(parentFolder, fileModel.getFileName() + "_" + i)));
                        while ((len = bufferedInputStream.read(bytes)) != -1) {
                            bufferedOutputStream.write(bytes, 0, len);
                        }
                    }
                    bufferedInputStream.close();
                    bufferedOutputStream.close();
                }


                for (int i = 1; i <= parentFolder.listFiles().length; i++) {
                    File splitFile = new File(parentFolder, fileModel.getFileName() + "_" + i);
                    if (splitFile.exists()) {
                        if (splitFile.delete()) {
                            logger.debug(splitFile.getName() + "刪除成功");
                        } else {
                            logger.error( splitFile.getName() + "刪除失敗");
                        }
                    }
                }

                result.setCode(200);
		        result.setMsg("上傳成功");
		        result.setData(fileModel.getFileName());
            } else {
                result.setCode(800);
                result.setMsg("上傳失敗");
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

}