Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不使用第三方API的情况下用C#压缩文件?_C#_Compression_Zip_Download - Fatal编程技术网

如何在不使用第三方API的情况下用C#压缩文件?

如何在不使用第三方API的情况下用C#压缩文件?,c#,compression,zip,download,C#,Compression,Zip,Download,我很确定这不是复制品,所以请耐心等我一会儿 如何在不使用任何第三方库的情况下以编程方式(在Windows中)压缩文件?我需要一个本地windows调用或类似的东西;我真的不喜欢开始一个过程的想法,但是如果我必须的话,我会的。打个皮诺维克电话会好得多 如果做不到这一点,让我告诉你我真正想要实现的目标:我需要让用户在一个请求中下载一组文档的能力。关于如何做到这一点,你有什么想法吗?你在使用.NET 3.5吗?您可以使用该类和相关类。它不仅仅是压缩一个文件列表,因为它希望为您添加的每个文件都有一个MI

我很确定这不是复制品,所以请耐心等我一会儿

如何在不使用任何第三方库的情况下以编程方式(在Windows中)压缩文件?我需要一个本地windows调用或类似的东西;我真的不喜欢开始一个过程的想法,但是如果我必须的话,我会的。打个皮诺维克电话会好得多


如果做不到这一点,让我告诉你我真正想要实现的目标:我需要让用户在一个请求中下载一组文档的能力。关于如何做到这一点,你有什么想法吗?

你在使用.NET 3.5吗?您可以使用该类和相关类。它不仅仅是压缩一个文件列表,因为它希望为您添加的每个文件都有一个MIME类型。它可以做你想做的事


我目前正在使用这些类解决一个类似的问题,将几个相关文件归档到一个文件中以供下载。我们使用文件扩展名将下载文件与桌面应用程序关联。我们遇到的一个小问题是,仅仅使用第三方工具(如7-zip)来创建zip文件是不可能的,因为客户端代码无法打开它——ZipPackage添加了一个描述每个组件文件的内容类型的隐藏文件,如果缺少该内容类型文件,则无法打开zip文件。

看起来Windows可能只是让你做


不幸的是,我认为除非您使用第三方组件,否则您将无法开始单独的流程

我也遇到了同样的情况,我想使用.NET而不是第三方库。正如上面提到的另一张海报,仅仅使用ZipPackage类(在.NET3.5中引入)是不够的。为了使ZipPackage正常工作,存档中还必须包含一个附加文件。如果添加了此文件,则可以直接从Windows资源管理器打开生成的ZIP包-没有问题

您只需将[Content\u Types].xml文件添加到归档文件的根目录中,每个文件扩展名都有一个“Default”节点。添加后,我可以从Windows资源管理器浏览该包,或通过编程方式解压缩并读取其内容

有关[Content\u Types].xml文件的详细信息,请参见:

以下是[Content\u Types].xml(必须准确命名)文件的示例:

注:

  • 此代码使用.NET 4.0中的Stream.CopyTo方法
  • 随着.NET 4.5中ZipArchive类的引入,这将变得更加简单:
在Windows中,我如何在不使用 有第三方图书馆吗

如果使用4.5+框架,现在就有了和类

您需要添加对以下内容的引用:

  • 系统IO压缩
  • System.IO.Compression.FileSystem
对于以net46为目标的.NET Core,您需要为添加依赖项

  • 系统IO压缩
  • 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,只需添加一个简单的using语句即可:

  • 使用System.IO.Compression

根据Simon McKenzie的回答,我建议使用以下两种方法:

    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);
    }
}
foreach (string f in UnitZipList)
{
    AddFileToZip(zipFile, f);
    System.IO.File.Delete(f);
}
Remove_Content_Types_FromZip(zipFile);

将以下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{}
        }
    }

哦,我是多么爱你!谢谢布莱恩;yuo为我们节省了很多麻烦和一些$$$。请注意,这并不总是起相反的作用。某些Zip文件不会使用ZipPackage类重新水化。使用ZipPackage创建的文件将被删除,因此您应该是好的。请注意,ZipPackage无法附加到现有的压缩包。叹气:“类型或命名空间”package“在命名空间“System.IO”中不存在”。(回答上述“叹气”:打开“引用”并添加(不合逻辑的)“WindowsBase”。)很好的示例,但它不会创建ZIP文件。它会解压现有文件。@Chesso:是的,从ASPX页面上。我发现这个示例在几周前搜索相同内容时很有用:如果使用4.5框架,现在就有ZipArchive和ZipFile类。有人使用DotNetZip吗?这怎么没有得到更多的投票?这是唯一可怕的ct答案。因为问题已经五年了,而这个答案只有两个月。Derp:-P@heliac但是Stackoverflow应该是一个问答库,从精神上讲,最好的答案应该在上面…(该死,我知道这不起作用)为了防止对任何人有帮助,第二个参数是文件条目。这是相对于解压文件夹提取文件的路径。在Windows 7中,我发现如果文件条目是完整路径,例如@“D:\Temp\file1.pdf,本机Windows提取器失败。如果只使用Directory.GetFiles()生成的文件名,可能会遇到此问题。最好使用Path.GetFileName()作为文件输入参数来提取文件名。我在4.5.2中似乎找不到这一点?当我在webapi中,接收HttpContext.Current.Request时,如何获取sourceFileName?压缩多个文件?
    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);
    }
}
    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");
    }
        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);