文件上传、下载、合并、分片、删除

文件上传、下载、合并、分片、删除


使用了Hutool工具类库

Controller层

除了 MultipartFile 其他参数可以忽视

/**
   * 前端上传文件
   *
   * @param file
   * @param proxyId
   * @return
   * @throws IOException
   */
  @PostMapping("/upload")
  public Result<Void> fileUpload(@RequestParam("file")MultipartFile file,
      String proxyId) throws IOException {
    fileListService.upload(file, proxyId);
    return Result.success();
  }
/**
   * 前端下载文件
   *
   * @param proxyId
   * @param name
   * @return
   * @throws IOException
   */
  @GetMapping("/download")
  public Result<String> download(@RequestParam("proxyId") String proxyId,
      @RequestParam("name") String name, String size, HttpServletResponse response)
      throws IOException {
    return fileListService.download(proxyId, name, size, response) ? Result.success("下载成功")
        : Result.failed("下载失败,请检查文件目录");
  }

Service层

上传文件

public void upload(MultipartFile multipartFile, String proxyId) throws IOException {
    //文件夹路径
    String folder = MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId;
    File dist = new File(folder);
    if (!dist.isDirectory()) {
      //文件夹不存在 --> 创建文件夹
      dist.mkdirs();
    }
    //文件夹 + 文件名(带后缀)
    File file = new File(folder + "/" + multipartFile.getOriginalFilename());
    multipartFile.transferTo(file);
  }

下载文件,这里包含了已分片文件合并成整个文件和删除文件操作

// 下载文件 --> 去OUTPUT目录查看是否有这个文件
// 无 --> 去INPUT目录查找目录,将文件分片合并成一个文件,到OUTPUT目录,并删除INPUT目录下的分片文件
// 有 --> 去OUTPUT目录下载文件
public boolean download(String proxyId, String name, String size, HttpServletResponse response)
      throws IOException {
    //1、判断是否存在这个文件
    // output/proxyId/name
    File folder = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
    log.info("去目录判断是否存在:" + MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
    //文件不存在 去合并文件
    if (!folder.exists()) {
      log.info(
          "文件不存在,去合并文件,合并目录内的文件:" + MqttConstants.FILE_PATH_INPUT + "/" + proxyId + "/" + name
              + "/");
      File input = new File(MqttConstants.FILE_PATH_INPUT + "/" + proxyId + "/" + name + "/");
      if (!input.exists()) {
        log.info("=============合并目录不存在=============");
        return false;
      } else {
        FilterByText filter = new FilterByText(name);
        String[] list = input.list(filter);
        assert list != null;
        byte[] bytes = new byte[Integer.parseInt(size)];
        int length = list.length;
        System.out.println("文件个数:" + length);
        BufferedOutputStream bufferedOutput = null;
        if (list.length != 0) {
          int count = 0;
          TimeInterval timer = DateUtil.timer();
          for (String str : list) {
            //#& --> 接收文件分片后重新命名文件,作为标识符的
            int i = Integer.parseInt(str.split("#&")[0]);
            File file = new File(input + "/" + str);
            count++;
            FileReader reader = new FileReader(file);
            byte[] bb = reader.readBytes();
            System.arraycopy(bb, 0, bytes, (i - 1) * 2, bb.length);
            File outFile = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId);
            if (!outFile.exists()) {
              outFile.mkdirs();
            }
            File out = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
            OutputStream output = new FileOutputStream(out);
            bufferedOutput = new BufferedOutputStream(output);
            bufferedOutput.write(bytes);
          }
          bufferedOutput.close();
          log.info("文件总个数:" + length + "个,合并了" + count + "个文件,共耗时" + timer.intervalSecond() + "秒");
        }
        //删除文件目录以及目录内容
        deleteDir(input);
      }
    }
    
    response.setHeader("Content-disposition", "attachment;filename=" + name);
    //拿到需要下载的文件
    File file = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
    //file转byte[]
    FileReader reader = new FileReader(file);
    byte[] bb = reader.readBytes();
    //文件大小
    response.addHeader("Content-Length", "" + file.length());
    ServletOutputStream outputStream = response.getOutputStream();
    outputStream.write(bb);
    outputStream.close();
    return true;
  }
    /**
   * 递归删除目录下的所有文件及子目录下所有文件
   *
   * @param dir 将要删除的文件目录
   * @return boolean Returns "true" if all deletions were successful. If a deletion fails, the
   * method stops attempting to delete and returns "false".
   */
  private static boolean deleteDir(File dir) {
    if (dir.isDirectory()) {
      String[] children = dir.list();
      //递归删除目录中的子目录下
      for (int i = 0; i < children.length; i++) {
        boolean success = deleteDir(new File(dir, children[i]));
        if (!success) {
          return false;
        }
      }
    }
    // 目录此时为空,可以删除
    return dir.delete();
  }

文件分片 这里将文件分片后 转成Base64通过MQTT发了出去

public Boolean setFile(String proxyId, String name)
      throws IOException, InterruptedException {
    String folder = MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId;
    File dist = new File(folder);
    if (!dist.isDirectory()) {
      return false;
    }
    //读取文件
    File file = new File(folder + "/" + name);
    FileReader reader = new FileReader(file);
    BufferedInputStream inputStream = reader.getInputStream();
    //file转byte[]
    byte[] bytes = reader.readBytes();
    int length = bytes.length;
    //这里是具体的业务逻辑了 可以忽视
    MqttMsg mqttMsg = new MqttMsg();
    mqttMsg.setServiceId(proxyId);
    mqttMsg.setClientId(MqttConstants.EMP);
    mqttMsg.setDirection(MqttConstants.DIRECTION_REQUEST);
    mqttMsg.setVersion(MqttConstants.VERSION_V1);
    mqttMsg.setDeviceId("xx");
    mqttMsg.setMId("xx");
    mqttMsg.setTimestamp("xx");
    mqttMsg.setExpire("xx");
    mqttMsg.setType(TopicType.SET_FILE);
    //字节小于10KB 不需要分片
    //这里可以根据自己的分片需要定义
    if (bytes.length < 10240) {
      JSONObject object = new JSONObject();
      object.put("name", name);
      object.put("total", "1");
      object.put("size", String.valueOf(length));
      object.put("current", "1");
      //Base64转换
      String base64 = Base64.getEncoder().encodeToString(bytes);
      object.put("data", base64);
      mqttMsg.setParams(object);
      mqttPublishService.publishRequest(mqttMsg, MqttConstants.QOS_1);
    } else {
      //字节大于 10KB 情况1整除 情况2非整除,有余数
      int yu = length % 10240;
      int split = length / 10240;
      byte[] bb = new byte[10240];
      //非整除,有余数 最后一片小于10KB 需特殊处理
      if (yu != 0) {
        for (int i = 0; i < split + 1; i++) {
        //最后一片 特殊处理
          if (i == split) {
            bb = new byte[i];
            inputStream.read(bb, 0, i);
          } else {
          //每片 10KB
            inputStream.read(bb, 0, 10240);
          }
          String base64 = Base64.getEncoder().encodeToString(bb);
          JSONObject object = new JSONObject();
          object.put("name", name);
          object.put("total", String.valueOf(split));
          object.put("size", String.valueOf(length));
          object.put("current", String.valueOf(i));
          object.put("data", base64);
          mqttMsg.setParams(object);
          mqttPublishService.publishRequest(mqttMsg, MqttConstants.QOS_1);
          //避免丢包 延时2ms
          Thread.sleep(2);
        }
      } else {
      //整除
        for (int i = 0; i < split; i++) {
          inputStream.read(bb, 0, 10240);
          String base64 = Base64.getEncoder().encodeToString(bb);
          JSONObject object = new JSONObject();
          object.put("name", name);
          object.put("total", String.valueOf(split));
          object.put("size", String.valueOf(length));
          object.put("current", String.valueOf(i));
          object.put("data", base64);
          mqttMsg.setParams(object);
          mqttPublishService.publishRequest(mqttMsg, MqttConstants.QOS_1);
          //避免丢包 延时2ms
          Thread.sleep(2);
        }
      }
    }
    return true;
  }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值