DEV Community

Masui Masanori
Masui Masanori

Posted on

[Micronaut] Generating and downloading files as ZIP or JSON

Intro

In this time, I will try generating and downloading files as ZIP.
If any error occurs during generation, generate and download a JSON file.

Generating a ZIP archive

First, I will load a CSV file and split it into multiple CSV files.

FileController.java

package jp.masanori; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.HttpResponse; import io.micronaut.http.server.types.files.SystemFile; @Controller("/files") public class FileController { private final ResultCsvGenerator csvGen; public FileController(ResultCsvGenerator csvGen) { this.csvGen = csvGen; } @Get(uri="zip") public HttpResponse<SystemFile> getZip() { SystemFile result = csvGen.generate(); return HttpResponse.ok(result) .contentType("application/zip"); } } 
Enter fullscreen mode Exit fullscreen mode

sample.csv

--12345678 Content-Disposition: mixed; name="sample"; filename="sample.csv"; Content-Type: text/csv id,名前,メッセージ,タグ 0,サンプル,こんにちは,debug 1,サンプル2,世界,world 2,サンプル3,こんばんは,debug 3,サンプル4,おはよう,morning --abcdefgh Content-Disposition: mixed; name="example"; filename="サンプル.csv"; Content-Type: text/csv id,名前,メッセージ,タグ 4,サンプル,こんにちは,debug 5,サンプル2,世界,world 6,サンプル3,こんばんは,debug 7,サンプル4,おはよう,morning 
Enter fullscreen mode Exit fullscreen mode

ResultCsvGenerator.java

package jp.masanori; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.micronaut.http.server.types.files.SystemFile; import jakarta.inject.Singleton; import jp.masanori.dto.ResultCsv; @Singleton public class ResultCsvGenerator { private final Logger logger; private final Pattern cdPattern; private final Pattern beiPattern; public ResultCsvGenerator() { this.logger = LoggerFactory.getLogger(ResultCsvGenerator.class); this.cdPattern = Pattern.compile("(Content-Disposition).+(filename=)\"(.+)\""); } public SystemFile generate() { try { byte[] fileData = Files .readAllBytes(Paths.get("C:/Users/example/sample.csv")); List<ResultCsv> csvValues = new ArrayList<>(); String name = ""; String value = ""; String[] splitted = new String(fileData, "SJIS").split("\n"); for (int i = 0; i < splitted.length; i++) { // split the value by "--" if (splitted[i].startsWith("--")) { if (name.length() <= 0) { continue; } ResultCsv result = new ResultCsv(name, value); csvValues.add(result); name = ""; value = ""; continue; } // get file names from "Content-Disposition" rows Matcher cdMatcher = cdPattern.matcher(splitted[i]); if (cdMatcher.find()) { name = cdMatcher.group(cdMatcher.groupCount()); continue; } // skip "Content-Type" rows if (splitted[i].startsWith("Content-Type")) { continue; } // add other rows as values if (name.length() > 0) { value += splitted[i]; value += "\n"; } } if(name.length() > 0) { ResultCsv result = new ResultCsv(name, value); csvValues.add(result); } return generateZipFile(csvValues); } catch(IOException ex) { logger.error("Failed generating a ZIP file", ex); return null; } } private SystemFile generateZipFile(List<ResultCsv> values) throws IOException { File tmpFile = File.createTempFile("result", "zip"); try (ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream( new FileOutputStream(tmpFile)))) { for (ResultCsv csv : values) { // add CSV files into ZIP archive String fileName = csv.getName(); if (fileName == null) { continue; } zip.putNextEntry(new ZipEntry(fileName)); byte[] value = csv.getValue().getBytes("SJIS"); zip.write(value, 0, value.length); } } // set ZIP file name return new SystemFile(tmpFile).attach("result.zip"); } } 
Enter fullscreen mode Exit fullscreen mode

ResultCsv.java

package jp.masanori.dto; public class ResultCsv { private String name; private String value; public String getName() { return name; } public String getValue() { return value; } public ResultCsv(String name, String value) { this.name = name; this.value = value; } } 
Enter fullscreen mode Exit fullscreen mode

Returning a JSON file when ZIP file generation fails

package jp.masanori; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.micronaut.http.server.types.files.SystemFile; public class ActionResult { private boolean succeeded; private String errorMessage; public boolean isSucceeded() { return succeeded; } public String getErrorMessage() { return errorMessage; } public static ActionResult getSucceeded() { ActionResult result = new ActionResult(); result.succeeded = true; return result; } public static ActionResult getFailed(String errorMessage) { ActionResult result = new ActionResult(); result.errorMessage = errorMessage; return result; } public static String getFailedJson(String errorMessage) throws JsonProcessingException { ActionResult result = ActionResult.getFailed(errorMessage); ObjectMapper mapper = new ObjectMapper(); return mapper.writeValueAsString(result); } public static SystemFile getFailedJsonFile(String errorMessage) throws IOException { String resultJson = ActionResult.getFailedJson(errorMessage); File tmpFile = File.createTempFile("result", "json"); try(FileOutputStream stream = new FileOutputStream(tmpFile)) { stream.write(resultJson.getBytes()); } return new SystemFile(tmpFile).attach("result.json"); } } 
Enter fullscreen mode Exit fullscreen mode

FileController.java

... @Get(uri="zip") public HttpResponse<SystemFile> getZip() { SystemFile result = csvGen.generate(); if(result == null) { try { return HttpResponse.ok(ActionResult.getFailedJsonFile("Failed generating a Zip file")); } catch(IOException ex) { return HttpResponse.serverError(); } } return HttpResponse.ok(result) .contentType("application/zip"); } ... 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)