无法打开从 System.IO.Compression 命名空间创建的 zip 文件
Can't open zip file created from System.IO.Compression namespace
我正在尝试压缩不同数量的文件,以便可以将一个 zip 文件夹提供给用户,而他们不必单击多个锚标记。我在 asp.net 核心 3.1 中使用 System.IO.Compression 命名空间来创建 zip 文件夹。
这是我用来创建 Zip 文件夹的代码。
public IActionResult DownloadPartFiles(string[] fileLocations, string[] fileNames)
{
List<InMemoryFile> files = new List<InMemoryFile>();
for (int i = 0; i < fileNames.Length; i++)
{
InMemoryFile inMemoryFile = GetInMemoryFile(fileLocations[i], fileNames[i]).Result;
files.Add(inMemoryFile);
}
byte[] archiveFile;
using (MemoryStream archiveStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
{
foreach (InMemoryFile file in files)
{
ZipArchiveEntry zipArchiveEntry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
using (Stream zipStream = zipArchiveEntry.Open())
{
zipStream.Write(file.Content, 0, file.Content.Length);
zipStream.Close();
}
}
archiveStream.Position = 0;
}
archiveFile = archiveStream.ToArray();
}
return File(archiveFile, "application/octet-stream");
}
我试图压缩的文件是远程存储的,所以我用这段代码抓取它们。 InMemoryFile 是一个 class 将文件名和文件字节组合在一起。
private async Task<InMemoryFile> GetInMemoryFile(string fileLocation, string fileName)
{
InMemoryFile file;
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(fileLocation))
{
byte[] fileContent = await response.Content.ReadAsByteArrayAsync();
file = new InMemoryFile(fileName, fileContent);
}
return file;
}
使用 Ajax 调用了 DownloadPartFiles 方法。我使用 javascript 获取文件的远程路径及其各自的名称,并将它们传递到 Ajax 调用中。
function downloadAllFiles() {
let partTable = document.getElementById("partTable");
let linkElements = partTable.getElementsByTagName('a');
let urls = [];
for (let i = 0; i < linkElements.length; i++) {
urls.push(linkElements[i].href);
}
if (urls.length != 0) {
var fileNames = [];
for (let i = 0; i < linkElements.length; i++) {
fileNames.push(linkElements[i].innerText);
}
$.ajax({
type: "POST",
url: "/WebOrder/DownloadPartFiles/",
data: { 'fileLocations': urls, 'fileNames': fileNames },
success: function (response) {
var blob = new Blob([response], { type: "application/zip" });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "PartFiles.zip";
link.click();
window.URL.revokeObjectURL(blob);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
}
}
现在我一直 运行 遇到的问题是我无法在 Windows 10 中打开 zip 文件夹。每次我尝试使用 Windows 或7-zip 我收到无法打开文件夹或文件夹无效的错误消息。我已经尝试在 Whosebug 上查看各种类似的问题,即 ,但仍然无法弄清楚这是为什么。
会不会是编码问题?我发现 Ajax 期望它的响应编码为 UTF-8,当我使用 notepad++ 和 UTF-8 查看 zip 文件时,我看到有 � 个字符表示损坏。
对此有任何想法都会有所帮助。如果需要更多信息,请告诉我。
如果需要损坏的 zip 文件之一,我也可以提供。
编辑:
我已经改变了我在 javascript 中接收字节数组的方法。我正在使用 XMLHttpRequest 接收字节数组。
var parameters = {};
parameters.FileLocations = urls;
parameters.FileNames = fileNames;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "/WebOrder/DownloadPartFiles/", true);
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.responseType = "arraybuffer";
xmlhttp.onload = function (oEvent) {
var arrayBuffer = xmlhttp.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
var blob = new Blob([byteArray], { type: "application/zip" });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "PartFiles.zip";
link.click();
window.URL.revokeObjectURL(blob);
}
}
xmlhttp.send(JSON.stringify(parameters));
据我了解,Ajax 不是接收字节数组和二进制数据的最佳选择。使用这种方法,我可以用 7-zip 打开其中一个 zip 文件,但不能 Windows,但是,存档中的一个文件显示为 0KB 大小,无法打开。存档中的其他三个文件都很好。但是,其他包含不同文件的 zip 文件夹根本无法打开。
一段时间后,我发现 post 可以解决我的问题,Create zip file from byte[]
由此 post 这是我用来创建包含文件的 zip 文件夹的修改方法。
public IActionResult DownloadPartFiles([FromBody] FileRequestParameters parameters)
{
List<InMemoryFile> files = new List<InMemoryFile>();
for (int i = 0; i < parameters.FileNames.Length; i++)
{
InMemoryFile inMemoryFile = GetInMemoryFile(parameters.FileLocations[i], parameters.FileNames[i]).Result;
files.Add(inMemoryFile);
}
byte[] archiveFile = null;
using (MemoryStream archiveStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
{
foreach (InMemoryFile file in files)
{
ZipArchiveEntry zipArchiveEntry = archive.CreateEntry(file.FileName, CompressionLevel.Optimal);
using (MemoryStream originalFileStream = new MemoryStream(file.Content))
using (Stream zipStream = zipArchiveEntry.Open())
{
originalFileStream.CopyTo(zipStream);
}
}
}
archiveFile = archiveStream.ToArray();
}
return File(archiveFile, "application/octet-stream");
}
我仍然不知道为什么以前的方法有问题,所以如果将来有人知道答案,我很想知道。
我正在尝试压缩不同数量的文件,以便可以将一个 zip 文件夹提供给用户,而他们不必单击多个锚标记。我在 asp.net 核心 3.1 中使用 System.IO.Compression 命名空间来创建 zip 文件夹。
这是我用来创建 Zip 文件夹的代码。
public IActionResult DownloadPartFiles(string[] fileLocations, string[] fileNames)
{
List<InMemoryFile> files = new List<InMemoryFile>();
for (int i = 0; i < fileNames.Length; i++)
{
InMemoryFile inMemoryFile = GetInMemoryFile(fileLocations[i], fileNames[i]).Result;
files.Add(inMemoryFile);
}
byte[] archiveFile;
using (MemoryStream archiveStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
{
foreach (InMemoryFile file in files)
{
ZipArchiveEntry zipArchiveEntry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
using (Stream zipStream = zipArchiveEntry.Open())
{
zipStream.Write(file.Content, 0, file.Content.Length);
zipStream.Close();
}
}
archiveStream.Position = 0;
}
archiveFile = archiveStream.ToArray();
}
return File(archiveFile, "application/octet-stream");
}
我试图压缩的文件是远程存储的,所以我用这段代码抓取它们。 InMemoryFile 是一个 class 将文件名和文件字节组合在一起。
private async Task<InMemoryFile> GetInMemoryFile(string fileLocation, string fileName)
{
InMemoryFile file;
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(fileLocation))
{
byte[] fileContent = await response.Content.ReadAsByteArrayAsync();
file = new InMemoryFile(fileName, fileContent);
}
return file;
}
使用 Ajax 调用了 DownloadPartFiles 方法。我使用 javascript 获取文件的远程路径及其各自的名称,并将它们传递到 Ajax 调用中。
function downloadAllFiles() {
let partTable = document.getElementById("partTable");
let linkElements = partTable.getElementsByTagName('a');
let urls = [];
for (let i = 0; i < linkElements.length; i++) {
urls.push(linkElements[i].href);
}
if (urls.length != 0) {
var fileNames = [];
for (let i = 0; i < linkElements.length; i++) {
fileNames.push(linkElements[i].innerText);
}
$.ajax({
type: "POST",
url: "/WebOrder/DownloadPartFiles/",
data: { 'fileLocations': urls, 'fileNames': fileNames },
success: function (response) {
var blob = new Blob([response], { type: "application/zip" });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "PartFiles.zip";
link.click();
window.URL.revokeObjectURL(blob);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
}
}
现在我一直 运行 遇到的问题是我无法在 Windows 10 中打开 zip 文件夹。每次我尝试使用 Windows 或7-zip 我收到无法打开文件夹或文件夹无效的错误消息。我已经尝试在 Whosebug 上查看各种类似的问题,即
会不会是编码问题?我发现 Ajax 期望它的响应编码为 UTF-8,当我使用 notepad++ 和 UTF-8 查看 zip 文件时,我看到有 � 个字符表示损坏。
对此有任何想法都会有所帮助。如果需要更多信息,请告诉我。
如果需要损坏的 zip 文件之一,我也可以提供。
编辑:
我已经改变了我在 javascript 中接收字节数组的方法。我正在使用 XMLHttpRequest 接收字节数组。
var parameters = {};
parameters.FileLocations = urls;
parameters.FileNames = fileNames;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "/WebOrder/DownloadPartFiles/", true);
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.responseType = "arraybuffer";
xmlhttp.onload = function (oEvent) {
var arrayBuffer = xmlhttp.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
var blob = new Blob([byteArray], { type: "application/zip" });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "PartFiles.zip";
link.click();
window.URL.revokeObjectURL(blob);
}
}
xmlhttp.send(JSON.stringify(parameters));
据我了解,Ajax 不是接收字节数组和二进制数据的最佳选择。使用这种方法,我可以用 7-zip 打开其中一个 zip 文件,但不能 Windows,但是,存档中的一个文件显示为 0KB 大小,无法打开。存档中的其他三个文件都很好。但是,其他包含不同文件的 zip 文件夹根本无法打开。
一段时间后,我发现 post 可以解决我的问题,Create zip file from byte[]
由此 post 这是我用来创建包含文件的 zip 文件夹的修改方法。
public IActionResult DownloadPartFiles([FromBody] FileRequestParameters parameters)
{
List<InMemoryFile> files = new List<InMemoryFile>();
for (int i = 0; i < parameters.FileNames.Length; i++)
{
InMemoryFile inMemoryFile = GetInMemoryFile(parameters.FileLocations[i], parameters.FileNames[i]).Result;
files.Add(inMemoryFile);
}
byte[] archiveFile = null;
using (MemoryStream archiveStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
{
foreach (InMemoryFile file in files)
{
ZipArchiveEntry zipArchiveEntry = archive.CreateEntry(file.FileName, CompressionLevel.Optimal);
using (MemoryStream originalFileStream = new MemoryStream(file.Content))
using (Stream zipStream = zipArchiveEntry.Open())
{
originalFileStream.CopyTo(zipStream);
}
}
}
archiveFile = archiveStream.ToArray();
}
return File(archiveFile, "application/octet-stream");
}
我仍然不知道为什么以前的方法有问题,所以如果将来有人知道答案,我很想知道。