티스토리 뷰

Java

[Java] File Download

Jane Kwon 2021. 2. 10. 18:17
반응형

 

로직 : 자바에서 JSON을 csv 파일로 만든 다음 zip 아카이브 파일로 압축하여 다운로드

* 이 때, 임시로 /tmp/ 디렉터리에 csv 파일과 zip 파일을 생성하여 response에 zip 파일을 내려준 후, 임시 디렉터리에 생성된 csv 파일과 zip 파일을 일정 시간 뒤에 삭제한다.

 

 

 

csv 파일 다운로드

컨트롤러 작성

@ApiOperation(value = "로그 리스트 전체 다운로드")
@GetMapping(value = "/download", produces = {MediaType.APPLICATION_JSON_VALUE})
public  ResponseEntity downloadUpdateLog(String uuid) throws Exception {
    String fileName = uuid + ".csv";

    HttpHeaders header = new HttpHeaders();
    header.add("Content-Type", "text/csv");
    header.add("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

    return new ResponseEntity(logService.downloadUpdateLog(uuid), header, HttpStatus.CREATED);
}

서비스 작성

public String downloadUpdateLog(String uuid) throws IllegalAccessException {
    String index = Constants.INDEX_PREFIX_NAME + "-" + uuid;
    String query = sourceBuilder.makeSearchQueryScroll();

    List<Map<String, Object>> data = new ArrayList<>();

    Map<String, Object> result = searchDAO.requestPostScrollSearch(index, query);
    List<Map<String, Object>> list;

    String scrollId = (String) result.get("_scroll_id");

    do {
      result = (Map<String, Object>) result.get("hits");
      list = (List<Map<String, Object>>) result.get("hits");

      for (Map<String, Object> log : list) {
        data.add(EsParseUtils.getValue(log, "_source"));
      }

      if (!StringUtils.isEmpty(scrollId)) {
        query = sourceBuilder.makeSearchQueryScroll(scrollId);
        result = searchDAO.requestPostScrollIdSearch(index, query);
      }
    } while (list.size() > 0);

    return createCSV(data);
}

private String createCSV(List<Map<String, Object>> list) throws IllegalAccessException {
    StringBuffer parameter = new StringBuffer();
    parameter.append("thingName,status,timestamp\n");

    for (Map<String, Object> data : list) {
      String thingName = (String) data.get("thingName");
      String status = (String) data.get("status");
      String timestamp = (String) data.get("timestamp");

      parameter.append(thingName).append(",")
          .append(status).append(",")
          .append(timestamp).append("\n");
    }
    parameter.delete(parameter.length()-2, parameter.length());

    return parameter.toString();
}

 

 

 

zip 파일 다운로드

컨트롤러 작성

@ApiOperation(value = "로그 리스트 전체 다운로드")
@GetMapping(value = "/download/{uuid}")
public ResponseEntity<InputStreamResource> downloadUpdateLog(@PathVariable String uuid) throws Exception {
    String fileName = uuid + "-" + UUID.randomUUID();
    String zipFileName = fileName + ".zip";

    MediaType mediaType = new MediaType("application","zip");

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(mediaType);
    httpHeaders.setContentDispositionFormData("attachment", zipFileName);

    return new ResponseEntity<InputStreamResource>(logService.downloadUpdateLog(uuid, fileName), httpHeaders, HttpStatus.OK);
}

서비스 작성

public InputStreamResource downloadUpdateLog(String uuid, String fileName) throws Exception {
    String path = "/tmp/";
    String csvFileName = fileName + ".csv";
    String zipFileName = fileName + ".zip";

    File file = null;
    FileWriter fileWriter = null;
    BufferedWriter bufferedWriter = null;

    try {
      // 임시 .csv 파일 생성
      file = new File(path + csvFileName);
      fileWriter = new FileWriter(file);
      bufferedWriter = new BufferedWriter(fileWriter);

      bufferedWriter.write("thingName,status,timestamp");

      String index = Constants.INDEX_PREFIX_NAME + "-" + uuid;
      String query = sourceBuilder.makeSearchQueryScroll();

      Map<String, Object> result = searchDAO.requestPostScrollSearch(index, query);

      String scrollId = (String) result.get("_scroll_id");
      List<Map<String, Object>> list;

      do {
        result = (Map<String, Object>) result.get("hits");
        list = (List<Map<String, Object>>) result.get("hits");

        for (Map<String, Object> log : list) {
          log = EsParseUtils.getValue(log, "_source");

          String thingName = (String) log.get("thingName");
          String status = (String) log.get("status");
          String timestamp = (String) log.get("timestamp");

          bufferedWriter.newLine();
          bufferedWriter.write(thingName + "," + status + "," + timestamp);
        }

        if (!StringUtils.isEmpty(scrollId)) {
          query = sourceBuilder.makeSearchQueryScroll(scrollId);
          result = searchDAO.requestPostScrollIdSearch(index, query);
        }
      } while (list.size() > 0);
    } catch (Exception e) {
      log.error("", e);
      throw new EsServiceException(e);
    } finally {
      if(bufferedWriter != null) {
        try{
          bufferedWriter.close();
        } catch(IOException e) {
          log.error("", e);
        }
      }

      if(fileWriter != null) {
        try{
          fileWriter.close();
        } catch(IOException e) {
          log.error("", e);
        }
      }
    }

    // 임시 .zip 파일 압축
    ZipUtils.fileCompress(path + csvFileName, path + zipFileName);

    // .zip 파일 다운로드
    File zipFile = new File(path + zipFileName);

    tempDataDeleteTimer(path + csvFileName);
    tempDataDeleteTimer(path + zipFileName);

    return new InputStreamResource(new FileInputStream(zipFile));
}

private void tempDataDeleteTimer(String fileName) {
    Timer timer = new Timer();
    TimerTask timerTask = new TimerTask() {
      @Override
      public void run() {
        File file = new File(fileName);
        if (file.delete()) {
          log.debug(fileName + " 파일 삭제");
        } else {
          log.debug(fileName + " 파일 삭제 실패");
        }
      }
    };

    timer.schedule(timerTask, 1000 * 60); // 60 seconds
}

ZipUtils

import lombok.extern.log4j.Log4j2;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Log4j2
public class ZipUtils {

  public static boolean directoryCompress(String path, String zipFileName) {
    File[] files = new File(path).listFiles();
    byte[] buf = new byte[4096];

    try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(path + zipFileName))) {
      for (int i=0; i<files.length; i++) {
        try (FileInputStream in = new FileInputStream(files[i])) {
          Path p = Paths.get(String.valueOf(files[i]));
          String fileName = p.getFileName().toString();

          ZipEntry ze = new ZipEntry(fileName);
          out.putNextEntry(ze);

          int len;
          while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
          }

          out.closeEntry();
        }
      }
    } catch (IOException e) {
      log.error(e);
      return false;
    }

    return true;
  }

  public static boolean fileCompress(String targetFile, String zipFile) {
    File file = new File(targetFile);
    byte[] buf = new byte[4096];

    try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))) {
      try (FileInputStream in = new FileInputStream(file)) {
        Path p = Paths.get(String.valueOf(file));
        String fileName = p.getFileName().toString();

        ZipEntry ze = new ZipEntry(fileName);
        out.putNextEntry(ze);

        int len;
        while ((len = in.read(buf)) > 0) {
          out.write(buf, 0, len);
        }

        out.closeEntry();
      }
    } catch (IOException e) {
      log.error(e);
      return false;
    }

    return true;
  }

}

 

 

 

 

 

반응형

'Java' 카테고리의 다른 글

[Java] JSP에서 Date 타입으로 파라미터 값 전달  (6) 2021.02.22
[Java] @RefreshScope  (0) 2021.02.10
[Java] Url 파일 다운로드  (0) 2021.02.10
[Java] Timestamp 비교  (0) 2021.02.10
[Java] 객체 정렬 방법 (Collections.sort())  (0) 2021.02.10
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함