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


    控制器
    /**
    * 上传文件
    *
    * @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);
    }


    实体Model
    public class MultipartFileParam {
    // uid
    private String uid;

    //总分片数量
    private int chunks;
    //当前为第几块分片
    private int chunk;

    //文件名
    private String name;
    //分片对象
    private MultipartFile file;
    // MD5
    private String md5;

    public String getUid() {
    return uid;
    }

    public void setUid(String uid) {
    this.uid = uid;
    }

    public int getChunks() {
    return chunks;
    }

    public void setChunks(int chunks) {
    this.chunks = chunks;
    }

    public int getChunk() {
    return chunk;
    }

    public void setChunk(int chunk) {
    this.chunk = chunk;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public MultipartFile getFile() {
    return file;
    }

    public void setFile(MultipartFile file) {
    this.file = file;
    }

    public String getMd5() {
    return md5;
    }

    public void setMd5(String md5) {
    this.md5 = md5;
    }

    }
  • 相关阅读:
    生命的等级
    一个笑话
    第一天的日记
    接吻鱼的秘密
    [转载] 女人到底想要什么??
    纪念一塌糊涂bbs
    上海市区找到一处比较便宜的打乒乓地方:)
    朋友在奔驰公司,给我提供的F1照片,奔驰必胜!
    前台mm何处有?
    一个令我感动的女孩!
  • 原文地址:https://www.cnblogs.com/gaozs/p/11514211.html
Copyright © 2020-2023  润新知