Как мне ZIP файл на С#, без использования сторонних API-интерфейсов?
Я уверен, что это не дубликат, так что медведь со мной на минуту.
Как я могу запрограммировать (С#) ZIP файл (в Windows) без использования каких-либо сторонних библиотек? Мне нужен собственный вызов Windows или что-то в этом роде; Мне действительно не нравится идея начать процесс, но я буду, если мне это абсолютно необходимо. Вызов PInovke будет намного лучше.
В противном случае позвольте мне рассказать вам, чего я действительно пытаюсь выполнить: мне нужно, чтобы пользователь мог загружать коллекцию документов в один запрос. Любые идеи о том, как это сделать?
Ответы
Ответ 1
Используете ли вы .NET 3.5? Вы можете использовать класс ZipPackage
и связанные классы. Это больше, чем просто перелистывание списка файлов, потому что для каждого добавляемого файла требуется тип MIME. Это может сделать то, что вы хотите.
В настоящее время я использую эти классы для аналогичной проблемы для архивирования нескольких связанных файлов в один файл для загрузки. Мы используем расширение файла, чтобы связать файл загрузки с нашим настольным приложением. Одна небольшая проблема, с которой мы столкнулись, заключалась в том, что не удалось использовать сторонний инструмент, такой как 7-zip, для создания zip файлов, потому что код на стороне клиента не может его открыть. ZipPackage добавляет скрытый файл, описывающий тип содержимого каждый файл компонента и не может открыть zip файл, если этот файл типа содержимого отсутствует.
Ответ 2
Как я могу программно (С#) ZIP файл (в Windows) без использования сторонних библиотек?
Если используется 4. 5+ Framework, теперь есть классы ZipArchive и ZipFile.
using (ZipArchive zip = ZipFile.Open("test.zip", ZipArchiveMode.Create))
{
zip.CreateEntryFromFile(@"c:\something.txt", "data/path/something.txt");
}
Вам необходимо добавить ссылки на:
- System.IO.Compression
- System.IO.Compression.FileSystem
Для .NET Core с таргетингом на net46 необходимо добавить зависимости для
- System.IO.Compression
- System.IO.Compression.ZipFile
Пример project.json:
"dependencies": {
"System.IO.Compression": "4.1.0",
"System.IO.Compression.ZipFile": "4.0.1"
},
"frameworks": {
"net46": {}
}
Для .NET Core 2.0 достаточно просто добавить простую инструкцию использования:
- использование System.IO.Compression;
Ответ 3
Я был в той же ситуации, желая .NET вместо сторонней библиотеки. В качестве другого плаката, упомянутого выше, просто использовать класс ZipPackage (представленный в .NET 3.5) недостаточно. Существует дополнительный файл, который ДОЛЖЕН быть включен в архив для работы ZipPackage. Если этот файл добавлен, то полученный ZIP-пакет можно открыть непосредственно из проводника Windows - без проблем.
Все, что вам нужно сделать, - добавить файл [Content_Types].xml в корень архива с "по умолчанию" node для каждого расширения файла, которое вы хотите включить. После добавления я мог просматривать пакет из Проводника Windows или программно распаковывать и читать его содержимое.
Дополнительную информацию о файле .xml [Content_Types] можно найти здесь: http://msdn.microsoft.com/en-us/magazine/cc163372.aspx
Вот пример файла [Content_Types].xml(должен быть назван точно):
<?xml version="1.0" encoding="utf-8" ?>
<Types xmlns=
"http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="xml" ContentType="text/xml" />
<Default Extension="htm" ContentType="text/html" />
<Default Extension="html" ContentType="text/html" />
<Default Extension="rels" ContentType=
"application/vnd.openxmlformats-package.relationships+xml" />
<Default Extension="jpg" ContentType="image/jpeg" />
<Default Extension="png" ContentType="image/png" />
<Default Extension="css" ContentType="text/css" />
</Types>
И С# для создания ZIP файла:
var zipFilePath = "c:\\myfile.zip";
var tempFolderPath = "c:\\unzipped";
using (Package package = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read))
{
foreach (PackagePart part in package.GetParts())
{
var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/')));
var targetDir = target.Remove(target.LastIndexOf('\\'));
if (!Directory.Exists(targetDir))
Directory.CreateDirectory(targetDir);
using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read))
{
source.CopyTo(File.OpenWrite(target));
}
}
}
Примечание:
Ответ 4
private static string CompressFile(string sourceFileName)
{
using (ZipArchive archive = ZipFile.Open(Path.ChangeExtension(sourceFileName, ".zip"), ZipArchiveMode.Create))
{
archive.CreateEntryFromFile(sourceFileName, Path.GetFileName(sourceFileName));
}
return Path.ChangeExtension(sourceFileName, ".zip");
}
Ответ 5
Для приложения .NET 2.0 я использовал SharpZipLib. Простой в использовании и с открытым исходным кодом.
Ответ 6
На основе Саймона Маккензи ответьте на этот вопрос, я бы предложил использовать пару таких методов:
public static void ZipFolder(string sourceFolder, string zipFile)
{
if (!System.IO.Directory.Exists(sourceFolder))
throw new ArgumentException("sourceDirectory");
byte[] zipHeader = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
using (System.IO.FileStream fs = System.IO.File.Create(zipFile))
{
fs.Write(zipHeader, 0, zipHeader.Length);
}
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic source = shellApplication.NameSpace(sourceFolder);
dynamic destination = shellApplication.NameSpace(zipFile);
destination.CopyHere(source.Items(), 20);
}
public static void UnzipFile(string zipFile, string targetFolder)
{
if (!System.IO.Directory.Exists(targetFolder))
System.IO.Directory.CreateDirectory(targetFolder);
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic compressedFolderContents = shellApplication.NameSpace(zipFile).Items;
dynamic destinationFolder = shellApplication.NameSpace(targetFolder);
destinationFolder.CopyHere(compressedFolderContents);
}
}
Ответ 7
Похоже, что Windows может просто позволить вам сделать this...
К сожалению, я не думаю, что вы собираетесь начать отдельный процесс, если не перейдете на сторонний компонент.
Ответ 8
Добавьте эти 4 функции в ваш проект:
public const long BUFFER_SIZE = 4096;
public static void AddFileToZip(string zipFilename, string fileToAdd)
{
using (Package zip = global::System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
{
string destFilename = ".\\" + Path.GetFileName(fileToAdd);
Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
if (zip.PartExists(uri))
{
zip.DeletePart(uri);
}
PackagePart part = zip.CreatePart(uri, "", CompressionOption.Normal);
using (FileStream fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read))
{
using (Stream dest = part.GetStream())
{
CopyStream(fileStream, dest);
}
}
}
}
public static void CopyStream(global::System.IO.FileStream inputStream, global::System.IO.Stream outputStream)
{
long bufferSize = inputStream.Length < BUFFER_SIZE ? inputStream.Length : BUFFER_SIZE;
byte[] buffer = new byte[bufferSize];
int bytesRead = 0;
long bytesWritten = 0;
while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0)
{
outputStream.Write(buffer, 0, bytesRead);
bytesWritten += bytesRead;
}
}
public static void RemoveFileFromZip(string zipFilename, string fileToRemove)
{
using (Package zip = global::System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
{
string destFilename = ".\\" + fileToRemove;
Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
if (zip.PartExists(uri))
{
zip.DeletePart(uri);
}
}
}
public static void Remove_Content_Types_FromZip(string zipFileName)
{
string contents;
using (ZipFile zipFile = new ZipFile(File.Open(zipFileName, FileMode.Open)))
{
/*
ZipEntry startPartEntry = zipFile.GetEntry("[Content_Types].xml");
using (StreamReader reader = new StreamReader(zipFile.GetInputStream(startPartEntry)))
{
contents = reader.ReadToEnd();
}
XElement contentTypes = XElement.Parse(contents);
XNamespace xs = contentTypes.GetDefaultNamespace();
XElement newDefExt = new XElement(xs + "Default", new XAttribute("Extension", "sab"), new XAttribute("ContentType", @"application/binary; modeler=Acis; version=18.0.2application/binary; modeler=Acis; version=18.0.2"));
contentTypes.Add(newDefExt);
contentTypes.Save("[Content_Types].xml");
zipFile.BeginUpdate();
zipFile.Add("[Content_Types].xml");
zipFile.CommitUpdate();
File.Delete("[Content_Types].xml");
*/
zipFile.BeginUpdate();
try
{
zipFile.Delete("[Content_Types].xml");
zipFile.CommitUpdate();
}
catch{}
}
}
И используйте их так:
foreach (string f in UnitZipList)
{
AddFileToZip(zipFile, f);
System.IO.File.Delete(f);
}
Remove_Content_Types_FromZip(zipFile);