1. 场景
一个环境下有多个集群,每个集群下有多个配置,这些配置保存在数据库中,需要提供一个接口用来下载整个环境下的配置(压缩包),压缩包的目录层次为
config.tar.gz/
├─ config/
│ ├─ yarn/
│ │ ├─ yarn-site.xml
│ ├─ hdfs/
│ │ ├─ core-site.xml
│ │ ├─ hdfs-site.xml
2. 代码
2.1 引入依赖
我们需要使用commons-compress来完成tar这种格式的压缩
2.2 实现
@Data
public static class ClusterClientConfig {
private String clusterName;
private List<ClientConfig> configs;
}
@Data
public static class ClientConfig {
private String filename;
private String content;
}
@SneakyThrows
public void download(List<ClusterClientConfig> clusters, HttpServletResponse response) {
String filenamePrefix = "config";
String filenameSuffix = ".tar.gz";
Path path = tarGzip(clusters, filenamePrefix, filenameSuffix);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment; filename=" + URLEncoder.encode(filenamePrefix + filenameSuffix, "UTF-8"));
try (InputStream from = Files.newInputStream(path); ServletOutputStream to = response.getOutputStream()) {
long length = ByteStreams.copy(from, to);
response.setContentLengthLong(length);
}
}
@SneakyThrows
private static Path tarGzip(List<ClusterClientConfig> clusters, String filenamePrefix, String filenameSuffix) {
Path outputTarGzip = Files.createTempFile(filenamePrefix, filenameSuffix);
try (OutputStream fOut = Files.newOutputStream(outputTarGzip);
BufferedOutputStream buffOut = new BufferedOutputStream(fOut);
GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(buffOut);
TarArchiveOutputStream tOut = new TarArchiveOutputStream(gzOut)) {
clusters.forEach(clusterClientConfig -> {
clusterClientConfig.configs.forEach(clientConfig -> {
String path= filenamePrefix + "/" + clusterClientConfig.clusterName + "/" + clientConfig.getFilename();
createTarArchiveEntry(path, clientConfig.getContent(), tOut);
});
});
tOut.finish();
}
return outputTarGzip;
}
@SneakyThrows
private static void createTarArchiveEntry(String fileName,
String data,
TarArchiveOutputStream tOut) {
byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
TarArchiveEntry tarEntry = new TarArchiveEntry(fileName);
tarEntry.setSize(bytes.length);
tOut.putArchiveEntry(tarEntry);
ByteStreams.copy(new ByteArrayInputStream(bytes), tOut);
tOut.closeArchiveEntry();
}