码迷,mamicode.com
首页 > 编程语言 > 详细

spring boot 大文件上传实现方式(一)

时间:2019-09-12 18:06:35      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:文件上传进度   one   opera   except   成功   chunk   https   flag   byte   

控制器
/**
* 上传文件
*
* @param param
* @param request
* @return
* @throws Exception
*/
@ApiOperation(value = "大文件上传")
@PostMapping(value = "/fileUpload")
@ResponseBody
public Result<String> fileUpload(MultipartFileParam param, HttpServletRequest request) {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
String parentId = request.getParameter("parentId");
if (isMultipart) {
logger.info("上传文件start。");
try {
personKnowledgeService.uploadFileByMappedByteBuffer(param,parentId);
} catch (IOException e) {
e.printStackTrace();
logger.error("文件上传失败。{}", param.toString());
return JsonError("上传失败");
}
logger.info("上传文件end。");
}
return JsonSuccess("上传成功");
}



实现方法


/**
* 上传文件方法2
* 处理文件分块,基于MappedByteBuffer来实现文件的保存
*
* @param param
* @throws IOException
*/
@Override
public void uploadFileByMappedByteBuffer(MultipartFileParam param, String parentId) throws IOException {

String basePath = System.getProperty("user.dir") + File.separator;
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String nowDayStr = sdf.format(now);
String filePath = "knowledge" + File.separator + "upload" + File.separator + nowDayStr + File.separator;

String fileName = param.getName();
String uploadDirPath = basePath + filePath + param.getUid();
String tempFileName = fileName + "_tmp";
File tmpDir = new File(uploadDirPath);
File tmpFile = new File(uploadDirPath, tempFileName);
if (!tmpDir.exists()) {
tmpDir.mkdirs();
}

//添加记录
long CHUNK_SIZE = 5242880;//5M
String uid = param.getUid();
PersonKnowledge model = personKnowledgeRepository.findFirstByFileuid(uid);
if (model == null) {
model = new PersonKnowledge();
model.setCreateTime(new Date());
model.setCreateId(SecurityUtils.getSubject().getCurrentUser().getId());
if (StringUtils.isEmpty(parentId)) {
parentId = "ROOT";
}
model.setParentId(parentId);
model.setAttchmentType(PersonKnowledgeType.文件.getId());
String suffixName = fileName.substring(fileName.lastIndexOf("."));
model.setName(fileName.substring(0, fileName.lastIndexOf("."))); // 新文件名
model.setAttachmentPath(uploadDirPath + File.separator + fileName); //文件路径
model.setSuffix(suffixName.toLowerCase().substring(1));
model.setFileuid(uid);
//获取文件大小
Long size = CHUNK_SIZE * param.getChunks();
String fileSizeString = "";
DecimalFormat df = new DecimalFormat("#.00");
if (size != null) {
if (size < 1024) {
fileSizeString = df.format((double) size) + "B";
model.setFileSize(fileSizeString);
} else if (size < 1048576) {
fileSizeString = df.format((double) size / 1024) + "K";
model.setFileSize(fileSizeString);
} else if (size < 1073741824) {
fileSizeString = df.format((double) size / 1048576) + "M";
model.setFileSize(fileSizeString);
} else {
fileSizeString = df.format((double) size / 1073741824) + "G";
model.setFileSize(fileSizeString);
}
}
personKnowledgeRepository.save(model);
}

RandomAccessFile tempRaf = new RandomAccessFile(tmpFile, "rw");
FileChannel fileChannel = tempRaf.getChannel();

//写入该分片数据

long offset = CHUNK_SIZE * param.getChunk();
byte[] fileData = param.getFile().getBytes();
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length);
mappedByteBuffer.put(fileData);
// 释放
FileMD5Util.freedMappedByteBuffer(mappedByteBuffer);
fileChannel.close();

boolean isOk = checkAndSetUploadProgress(param, uploadDirPath);
if (isOk) {
boolean flag = renameFile(tmpFile, fileName);
System.out.println("upload complete !!" + flag + " name=" + fileName);
}
}

/**
* 检查并修改文件上传进度
*
* @param param
* @param uploadDirPath
* @return
* @throws IOException
*/
private boolean checkAndSetUploadProgress(MultipartFileParam param, String uploadDirPath) throws IOException {
String fileName = param.getName();
File confFile = new File(uploadDirPath, fileName + ".conf");
RandomAccessFile accessConfFile = new RandomAccessFile(confFile, "rw");
//把该分段标记为 true 表示完成
System.out.println("set part " + param.getChunk() + " complete");
accessConfFile.setLength(param.getChunks());
accessConfFile.seek(param.getChunk());
accessConfFile.write(Byte.MAX_VALUE);

//completeList 检查是否全部完成,如果数组里是否全部都是(全部分片都成功上传)
byte[] completeList = FileUtils.readFileToByteArray(confFile);
byte isComplete = Byte.MAX_VALUE;
for (int i = 0; i < completeList.length && isComplete == Byte.MAX_VALUE; i++) {
//与运算, 如果有部分没有完成则 isComplete 不是 Byte.MAX_VALUE
isComplete = (byte) (isComplete & completeList[i]);
System.out.println("check part " + i + " complete?:" + completeList[i]);
}

accessConfFile.close();
if (isComplete == Byte.MAX_VALUE) {
//stringRedisTemplate.opsForHash().put(Constants.FILE_UPLOAD_STATUS, param.getMd5(), "true");
//stringRedisTemplate.opsForValue().set(Constants.FILE_MD5_KEY + param.getMd5(), uploadDirPath + "/" + fileName);
return true;
} else {
// if (!stringRedisTemplate.opsForHash().hasKey(Constants.FILE_UPLOAD_STATUS, param.getMd5())) {
// stringRedisTemplate.opsForHash().put(Constants.FILE_UPLOAD_STATUS, param.getMd5(), "false");
// }
// if (stringRedisTemplate.hasKey(Constants.FILE_MD5_KEY + param.getMd5())) {
// stringRedisTemplate.opsForValue().set(Constants.FILE_MD5_KEY + param.getMd5(), uploadDirPath + "/" + fileName + ".conf");
// }
return false;
}
}

/**
* 文件重命名
*
* @param toBeRenamed 将要修改名字的文件
* @param toFileNewName 新的名字
* @return
*/
public boolean renameFile(File toBeRenamed, String toFileNewName) {
//检查要重命名的文件是否存在,是否是文件
if (!toBeRenamed.exists() || toBeRenamed.isDirectory()) {
//logger.info("File does not exist: " + toBeRenamed.getName());
return false;
}
String p = toBeRenamed.getParent();
File newFile = new File(p + File.separatorChar + toFileNewName);
//修改文件名
return toBeRenamed.renameTo(newFile);
}

spring boot 大文件上传实现方式(一)

标签:文件上传进度   one   opera   except   成功   chunk   https   flag   byte   

原文地址:https://www.cnblogs.com/gaozs/p/11514211.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!