大文件数据分片上传简单示例

版权声明:士,不可以不弘毅,任重而道远 https://blog.csdn.net/superbeyone/article/details/84246740


大文件数据分片上传简单示例

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;
    }

}

猜你喜欢

转载自blog.csdn.net/superbeyone/article/details/84246740
今日推荐