大家好我想实现一个zip下载。我有一个网络应用程序,用户可以单击按钮:
<template>
<button name="exportButton" id="exportButton" @click="convertConfigurationToZip" :class="['button']">{{
exportConfig
}}
</button>
</template>
methods: {
async convertConfigurationToZip() {
// Stores the current config in "store.config"
RestResource.convertConfigurationToZip();
const configData = store.config;
await new Promise((resolve) => setTimeout(resolve, 2000));
// A Blob represents raw binary data
const blob = new Blob([configData], {type: 'application/zip'});
// Use file-saver to trigger the download
saveAs(blob, 'ProCAKE_Configuration')
RestResource中调用的函数如下:
convertConfigurationToZip: () => {
axios
.get("http://localhost:8080/api/conversion/convertConfigurationToZip/")
.then((response: any) => {
console.log(response.data);
store.config = response.data;
})
.catch((error: any) => {
console.log(error);
})
}
被调用的控制器如下所示:
package controller;
import io.swagger.annotations.*;
import jakarta.annotation.Resource;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.container.AsyncResponse;
import jakarta.ws.rs.container.Suspended;
import jakarta.ws.rs.core.Response;
import services.ConversionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// This Controller should be used for creating zip files that contains the ProCake-Configuration
@Api(tags = "Conversion Controller", authorizations = { @Authorization(value = "basicAuth") })
@Path("/conversion")
public class ConversionController
{
@Resource
ExecutorService executorService;
@ApiOperation(value = "Convert Config into Zip")
@ApiResponses({ @ApiResponse(code = 200, message = "Config as Zip"), @ApiResponse(code = 503, message = "ProCAKE not started/configured properly") })
@GET
@Path("/convertConfigurationToZip")
public void convertConfigurationToZip(@Suspended final AsyncResponse response)
{
executorService = Executors.newSingleThreadExecutor();
executorService.submit(() ->
{
try
{
response.resume(Response.status(200).entity(new ConversionService().convertConfigurationToZip()).build());
}
catch (Exception e)
{
response.resume(e);
}
executorService.shutdown();
});
}
}
处理 Zip 文件的服务如下所示:
package services;
import de.uni_trier.wi2.procake.data.model.Model;
import de.uni_trier.wi2.procake.data.model.ModelFactory;
import de.uni_trier.wi2.procake.similarity.SimilarityModel;
import de.uni_trier.wi2.procake.similarity.SimilarityModelFactory;
import de.uni_trier.wi2.procake.utils.io.IOUtil;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.jena.sparql.exec.RowSet;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipInputStream;
public class ConversionService
{
public byte[] convertConfigurationToZip() throws IOException
{
try
{
// Create Zip on Harddrive
List<File> listOfFiles = new ArrayList<File>();
File hello = new File("pathToFile");
File world = new File("pathToFile");
listOfFiles.add(hello);
listOfFiles.add(world);
IOUtil.createZipFile("pathToZip", listOfFiles);
// ---------------------
// Create Zip File in Memory
ByteArrayOutputStream baos = IOUtil.createZipFileInMemory(listOfFiles);
;
// ---------------------
// Compare both Zip Files
byte[] zipContentHardDrive = Files.readAllBytes(Paths.get("pathToFile"));
byte[] zipContentMemory = baos.toByteArray();
int minLength = Math.min(zipContentMemory.length, zipContentHardDrive.length);
if (!Arrays.equals(
Arrays.copyOf(zipContentMemory, minLength),
Arrays.copyOf(zipContentHardDrive, minLength))) {
throw new IOException("The Zip Files are different.");
}
// ---------------------
return zipContentMemory;
}catch (Exception e) {
System.out.println("Could not create Zip File");
}
return null;
}
}
最后,在我详细介绍我的问题之前,这里是 IOUtil 方法:
public static ByteArrayOutputStream createZipFileInMemory(List<File> files) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(
byteArrayOutputStream);
for (File file : files) {
addZipEntry(zipArchiveOutputStream, file);
}
zipArchiveOutputStream.finish();
return byteArrayOutputStream;
}
private static void addZipEntry(ArchiveOutputStream archiveOutputStream, File file)
throws IOException {
String entryName = file.getName();
ArchiveEntry archiveEntry = new ZipArchiveEntry(file, entryName);
archiveOutputStream.putArchiveEntry(archiveEntry);
if (file.isFile()) {
Files.copy(file.toPath(), archiveOutputStream);
}
archiveOutputStream.closeArchiveEntry();
}
createZipFile 工作完全正常。 我的问题是,我从下载中获得的 zip 文件比我直接在硬盘上创建的文件大 200 字节左右。我也无法打开更大的 zip 文件。用 vim 打开较大的 zip 文件后,我可以看到内容与较小的 zip 文件完全不同:
较小的拉链: " zip.vim 版本 v33 " 浏览 zip 文件路径ToZip " 用光标选择文件并按 ENTER
你好.txt 世界.txt
这是更大的一个: PK^C^D^T^@^H^H^H^@���W^@^@^@^@^@^@^@^@^@^@^@^@ ^@5^@ hello.txtUT^M^@^G���eִ�e���e
我不知道我在内存中创建 zip 文件的方法是否错误,或者传输到 store.config 时是否出现问题。 还有一件事值得注意的是 zipContentHardDrive 和 zipContentMemory 是不同的: zip内容硬盘: [80, 75, 3, 4, 20, 0, 0, 8, 8, 0, -72, -114, -103, 87, 32, 48, 58, 54, 8, 0, 0, 0, 6, 0、0、0、9、0、53、0、104、101、108、108、111、46、116、120、116、85、84、13、0、7、-99、-77、-119 , 101, -42, -76, -119, 101, -99, -77, -119, 101, 10, 0, 32, 0, 0, 0, 0, 0, 1, 0, 24, 0, - 106, 85, -35, -18, 82, 55, -38, 1, 4, 18, -88, -87, 83, 55, -38, 1, -128, 76, -114, -18, 82 , 55, -38, 1, -53, 72, -51, -55, -55, -25, 2, 0, +322 更多]
zip内容内存: [80, 75, 3, 4, 20, 0, 8, 8, 8, 0, -72, -114, -103, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0、0、0、9、0、53、0、104、101、108、108、111、46、116、120、116、85、84、13、0、7、-99、-77、-119 , 101, -42, -76, -119, 101, -99, -77, -119, 101, 10, 0, 32, 0, 0, 0, 0, 0, 1, 0, 24, 0, - 106, 85, -35, -18, 82, 55, -38, 1, 4, 18, -88, -87, 83, 55, -38, 1, -128, 76, -114, -18, 82 , 55, -38, 1, -53, 72, -51, -55, -55, -25, 2, 0, +354 更多]
我不确定是否是这样,因为 zip 文件在内存中和不在内存中时通常是不同的。
如果有人能帮助我理解并解决我的问题,我将非常感激。 非常感谢您抽出时间!
更新1 经过以下测试后,我发现由于未知原因,createZipFileInMemory 方法无法像 CoonversionService 中那样工作。
@Test
public void testCreateZipFileInMemoryWithFiles() throws IOException {
IOUtil.writeFile(graph, PATH_GRAPH_TXT);
IOUtil.writeFile(graph, PATH_GRAPH_XML);
File fileText = new File(PATH_GRAPH_TXT);
File fileXML = new File(PATH_GRAPH_XML);
List<File> listOfFiles = new ArrayList<>();
listOfFiles.add(fileText);
listOfFiles.add(fileXML);
ByteArrayOutputStream zipFileInMemory = IOUtil.createZipFileInMemory(listOfFiles);
assertNotNull(zipFileInMemory);
// Now let's check if the data stored in the memory is actually the right Zip-file
// Therefore let's create an actual Zip-File on our hard drive
IOUtil.createZipFile(PATH_CREATED_ZIP, listOfFiles);
// Read the content of the created zip file
byte[] actualZipContent = Files.readAllBytes(Paths.get(PATH_CREATED_ZIP));
// Compare the contents of the files within the zip
ZipInputStream dataOfMemoryZip = new ZipInputStream(new ByteArrayInputStream(zipFileInMemory.toByteArray()));
ZipInputStream dataOfHardDriveZip = new ZipInputStream(new ByteArrayInputStream(actualZipContent));
ZipEntry memoryEntry;
ZipEntry hardDriveEntry;
while ((memoryEntry = dataOfMemoryZip.getNextEntry()) != null) {
hardDriveEntry = dataOfHardDriveZip.getNextEntry();
assertEquals(memoryEntry.getName(), hardDriveEntry.getName());
byte[] expectedFileContent = IOUtils.toByteArray(dataOfMemoryZip);
byte[] actualFileContent = IOUtils.toByteArray(dataOfHardDriveZip);
assertArrayEquals(expectedFileContent, actualFileContent);
}
}
这里的内容总是一样的。我不明白为什么 ConversionService 类中的内容不同,因为我使用相同的文件和相同的方法。
您创建的 zip 文件的部分十进制转储确实不同。
zipContentMemory
已创建 streamed zip 文件,而 zipContentHarddrive
尚未创建。这足以解释为什么一个 zip 文件可以工作,而另一个却不能。
注意:如果没有看到完整的 zip 文件,就不可能 100% 确定这一点。 zip 文件中可能存在一些其他差异,导致您遇到问题。如果有机会的话,发布完整的 zip 转储。
部分
zipContentHarddrive
zip 文件看起来像这样
0000 LOCAL HEADER #1 04034B50 (67324752)
0004 Extract Zip Spec 14 (20) '2.0'
0005 Extract OS 00 (0) 'MS-DOS'
0006 General Purpose Flag 0800 (2048)
[Bits 1-2] 0 'Normal Compression'
[Bit 11] 1 'Language Encoding'
0008 Compression Method 0008 (8) 'Deflated'
000A Last Mod Date/Time 57E6F1C7 (1474752967) 'Invalid Date or Time'
000E CRC 363A3020 (909783072)
0012 Compressed Size 00000008 (8)
0016 Uncompressed Size 00000006 (6)
001A Filename Length 0009 (9)
001C Extra Length 0035 (53)
001E Filename 'hello.txt'
0027 Extra ID #1 5455 (21589) 'Extended Timestamp [UT]'
0029 Length 000D (13)
002B Flags 07 (7) 'mod access change'
002C Mod Time 65F6CCE2 (1710673122) 'Sun Mar 17 10:58:42 2024'
0030 Access Time 65F6CBA9 (1710672809) 'Sun Mar 17 10:53:29 2024'
0034 Change Time 65F6CCE2 (1710673122) 'Sun Mar 17 10:58:42 2024'
0038 Extra ID #2 000A (10) 'NTFS FileTimes'
003A Length 0020 (32)
003C Reserved 00000000 (0)
0040 Tag1 0001 (1)
0042 Size1 0018 (24)
0044 Mtime 01A5375291A255E9 (118561792965367273) 'Thu Sep 16 07:08:16 1976 536727300ns'
004C Atime 01A53753D6D71204 (118561798421418500) 'Thu Sep 16 07:17:22 1976 141850000ns'
0054 Ctime 01A5375291F14CFF (118561792970542335) 'Thu Sep 16 07:08:17 1976 54233500ns'
部分
zipContentMemory
zip 文件看起来像这样
0000 LOCAL HEADER #1 04034B50 (67324752)
0004 Extract Zip Spec 14 (20) '2.0'
0005 Extract OS 00 (0) 'MS-DOS'
0006 General Purpose Flag 0808 (2056)
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
[Bit 11] 1 'Language Encoding'
0008 Compression Method 0008 (8) 'Deflated'
000A Last Mod Date/Time 57E6F1C7 (1474752967) 'Invalid Date or Time'
000E CRC 00000000 (0)
0012 Compressed Size 00000000 (0)
0016 Uncompressed Size 00000000 (0)
001A Filename Length 0009 (9)
001C Extra Length 0035 (53)
001E Filename 'hello.txt'
0027 Extra ID #1 5455 (21589) 'Extended Timestamp [UT]'
0029 Length 000D (13)
002B Flags 07 (7) 'mod access change'
002C Mod Time 65F6CCE2 (1710673122) 'Sun Mar 17 10:58:42 2024'
0030 Access Time 65F6CBA9 (1710672809) 'Sun Mar 17 10:53:29 2024'
0034 Change Time 65F6CCE2 (1710673122) 'Sun Mar 17 10:58:42 2024'
0038 Extra ID #2 000A (10) 'NTFS FileTimes'
003A Length 0020 (32)
003C Reserved 00000000 (0)
0040 Tag1 0001 (1)
0042 Size1 0018 (24)
0044 Mtime 01A5375291A255E9 (118561792965367273) 'Thu Sep 16 07:08:16 1976 536727300ns'
004C Atime 01A53753D6D71204 (118561798421418500) 'Thu Sep 16 07:17:22 1976 141850000ns'
0054 Ctime 01A5375291F14CFF (118561792970542335) 'Thu Sep 16 07:08:17 1976 54233500ns'