NIO断点续传

断点续传一般在header中需要携带Content-Range

后端接收该header,正则校验如下:

public static final String RANGE_PATTERN = "bytes \\d+-\\d+/\\d+";

上传的时候,加一张临时表,文件信息保存到临时表,并生成一个UUID,上传完成了再插入到主表,并返回前端一个文件的fileId

代码如下:

@Override
	@Transactional(rollbackFor = Exception.class)
	public UploadResumeDTO uploadFileResume(MultipartFile file,
	                                        UploadFileResumeRequest uploadFileResumeRequest,
	                                        String range) {
		long start = System.currentTimeMillis();
		Long fileId = null;
		InputStream inputStream = null;
		FileInputStream fileInputStream;
		FileChannel inChannel = null;
		FileOutputStream outStream = null;
		FileChannel outChannel = null;
		long uploadSize = 0;
		long length = 0;
		// 解析Content-Range
		int startByte = 0;
		int endByte = 0;
		try {
			String bytes = range.replaceAll("bytes", "").trim();
			String[] split = bytes.split("-");
			startByte = Integer.parseInt(split[0]);
			String[] split1 = split[1].split("/");
			endByte = Integer.parseInt(split1[0]);
		} catch (Exception e) {
			log.error("header=====>Content-Range转换失败:{}", range);
		}

		// 文件上传
		FileTemp fileTemp = new FileTemp();
		BeanUtils.copyProperties(uploadFileResumeRequest, fileTemp);
		File destFile = new File(config.getRootPath() + file.getOriginalFilename());
		try {
			if (!destFile.exists()) {
				destFile.createNewFile();
			}
			length = destFile.length();
			// 避免重复上传文件
			if (uploadSize + length >= uploadFileResumeRequest.getFileSize()) {
				return UploadResumeDTO.builder()
						.uuid(uploadFileResumeRequest.getUuid())
						.fileSize(uploadSize + length)
						.build();
			}
			inputStream = file.getInputStream();
			fileInputStream = (FileInputStream) inputStream;
			inChannel = fileInputStream.getChannel();
			outStream = new FileOutputStream(destFile, true);
			outChannel = outStream.getChannel();
			// 第二个参数为传多少字节
			uploadSize = inChannel.transferTo(startByte, endByte - startByte, outChannel);

			log.debug("总上传:{}", uploadSize);
			log.debug("文件目前大小:{}", uploadSize + length);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (inputStream != null) {
					inputStream.close();
				}
				if (outStream != null) {
					outStream.close();
				}
				if (inChannel != null) {
					inChannel.close();
				}
				if (outChannel != null) {
					outChannel.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		List<FileTemp> tempList = getTempFile(uploadFileResumeRequest.getUuid());
		// 首次上传
		if (CollectionUtils.isEmpty(tempList)) {
			log.info("不存在临时文件:{}", uploadFileResumeRequest.getUuid());
			// 上传完成
			if (uploadFileResumeRequest.getFileSize() == uploadSize + length) {
				// 首次就上传完,直接插入到主表
				DeviceFileInfoVO deviceFileInfoVO = new DeviceFileInfoVO();
				BeanUtils.copyProperties(uploadFileResumeRequest, deviceFileInfoVO);
				deviceFileInfoVO.setSourceType(uploadFileResumeRequest.getSourceType().getCode());
				deviceFileInfoVO.setFileName(file.getOriginalFilename());
				deviceFileInfoVO.setFilePath(config.getRootPath());
				devMapper.insert(deviceFileInfoVO);
				fileId = deviceFileInfoVO.getFileId();
			} else {
				// 没有上传完成,则插入临时表
				fileTemp.setFilePath(config.getRootPath());
				fileTemp.setFileName(file.getOriginalFilename());
				fileTemp.setFileSize(uploadSize + length);
				fileTempMapper.insert(fileTemp);
			}
		}
		// 非首次上传
		if (CollectionUtils.isNotEmpty(tempList)) {
			// 非首次,临时表已经存在记录
			if (uploadFileResumeRequest.getFileSize() == uploadSize + length) {
				// 上传完,直接插入到主表
				DeviceFileInfoVO deviceFileInfoVO = new DeviceFileInfoVO();
				BeanUtils.copyProperties(uploadFileResumeRequest, deviceFileInfoVO);
				deviceFileInfoVO.setSourceType(uploadFileResumeRequest.getSourceType().getCode());
				deviceFileInfoVO.setFileName(file.getOriginalFilename());
				deviceFileInfoVO.setFilePath(config.getRootPath());
				devMapper.insert(deviceFileInfoVO);
				fileId = deviceFileInfoVO.getFileId();
				fileTempMapper.deleteById(fileTemp);
			} else {
				fileTemp = tempList.get(0);
				fileTemp.setFileSize(uploadSize + length);
				fileTempMapper.updateById(fileTemp);
			}
		}
		log.info("耗时:{} ms", System.currentTimeMillis() - start);
		return UploadResumeDTO.builder()
				.uuid(uploadFileResumeRequest.getUuid())
				.fileSize(uploadSize + length)
				.fileId(fileId == null ? null : fileId.toString())
				.build();
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值