Reputation: 2813
I've written the following method to create a ZIP archive
public class ZipUtils {
public static byte[] createZipArchive(Collection<FileWrapper> sourceFiles) throws IOException {
try (var bytesOut = new ByteArrayOutputStream(); var zipOut = new ZipOutputStream(bytesOut)) {
for (var sourceFile : sourceFiles) {
try (var fileContent = sourceFile.getResource().getInputStream()) {
var zipEntry = new ZipEntry(sourceFile.getFileName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fileContent.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
}
}
zipOut.flush();
return bytesOut.toByteArray();
}
}
}
FileWrapper
is a simple data class that encapsulates a file's content and it's name
import org.springframework.core.io.Resource;
public class FileWrapper {
private final String fileName;
private final Resource resource;
// getters, setters, constructors omitted
}
I've written the following unit test
public class ZipUtilsTests {
@Test
void createZipArchive() throws IOException {
var file1 = getFile("src/test/resources/json/event.json");
var file2 = getFile("src/test/resources/json/label.json");
var zipData = ZipUtils.createZipArchive(Set.of(file1, file2));
File zipOutput = File.createTempFile("2-json-files", ".zip");
logger.debug("Writing ZIP archive to: " + zipOutput.getAbsolutePath());
Files.write(zipOutput.toPath(), zipData);
}
private FileWrapper getFile(String path) throws IOException {
var bytes = Files.readAllBytes(Paths.get(path));
var resource = new ByteArrayResource(bytes);
var fileName = StringUtils.substringAfterLast(path, '/');
return new FileWrapper(fileName, resource);
}
}
If I navigate to the ZIP file this test creates and try to unzip it, I get the following error
The size of the file is roughly what I would expect, but there's obviously something wrong with it because extraction of the files fails.
Upvotes: 1
Views: 151
Reputation: 26
try this:
try(var bytesOut = new ByteArrayOutputStream()) {
try (var zipOut = new ZipOutputStream(bytesOut)) {
for (var sourceFile : sourceFiles) {
try (var fileContent = sourceFile.getResource().getInputStream()) {
var zipEntry = new ZipEntry(sourceFile.getFileName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fileContent.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
}
}
}
return bytesOut.toByteArray();
}
You need that zipOut is closed before you return byte array.
I hope help you
Upvotes: 1
Reputation: 1104
just add:
zipOut.closeEntry();
zipOut.close();
before return bytesOut.toByteArray();
Done.
Upvotes: 1