Masui Masanori
Posted on April 7, 2024
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");
}
}
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
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");
}
}
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;
}
}
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");
}
}
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");
}
...
💖 💪 🙅 🚩
Masui Masanori
Posted on April 7, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.