2009-06-02 20 views
139

Tôi khá chắc chắn đây không phải là bản sao nên hãy chịu đựng tôi chỉ trong một phút.Tôi làm cách nào để nén tệp trong C#, không sử dụng API của bên thứ ba?

Làm cách nào để lập trình (C#) ZIP một tệp (trong Windows) mà không sử dụng bất kỳ thư viện của bên thứ ba nào? Tôi cần một cuộc gọi cửa sổ bản địa hoặc một cái gì đó như thế; Tôi thực sự không thích ý tưởng bắt đầu một quá trình, nhưng tôi sẽ nếu tôi hoàn toàn phải làm vậy. Một cuộc gọi PInovke sẽ tốt hơn nhiều.

Nếu không, hãy để tôi cho bạn biết những gì tôi thực sự đang cố gắng hoàn thành: Tôi cần khả năng cho phép người dùng tải xuống bộ sưu tập tài liệu trong một yêu cầu. Bất kỳ ý tưởng về cách thực hiện điều này?

+1

tải về từ một trang web? – Cheeso

+1

@Chesso: Có, từ trang ASPX. –

+1

Tôi thấy ví dụ này hữu ích khi tôi đang tìm kiếm cùng một điều một vài tuần trước: http://www.syntaxwarriors.com/2012/zip-files-using-c-net-without-any-extra-libraries/ – JensB

Trả lời

80

Bạn đang sử dụng .NET 3.5? Bạn có thể sử dụng lớp ZipPackage và các lớp liên quan. Nhiều hơn là chỉ nén một danh sách tập tin vì nó muốn loại MIME cho mỗi tệp bạn thêm vào. Nó có thể làm những gì bạn muốn.

Tôi hiện đang sử dụng các lớp này cho một sự cố tương tự để lưu trữ một số tệp có liên quan vào một tệp duy nhất để tải xuống. Chúng tôi sử dụng phần mở rộng tệp để liên kết tệp tải xuống với ứng dụng dành cho máy tính để bàn của chúng tôi. Một vấn đề nhỏ mà chúng tôi gặp phải là không thể sử dụng công cụ của bên thứ ba như 7-zip để tạo tệp zip vì mã phía máy khách không thể mở nó - ZipPackage thêm tệp ẩn mô tả loại nội dung của mỗi tệp thành phần và không thể mở tệp zip nếu thiếu loại tệp nội dung đó.

+0

Điều này đã hoạt động tốt trong quá khứ đối với tôi. – David

+1

Oh SO, tôi yêu bạn như thế nào! Cảm ơn Brian; yuo chỉ cứu chúng tôi rất nhiều đau đầu và một số $$$. –

+5

Lưu ý rằng điều này không phải lúc nào cũng hoạt động ngược lại. Một số tệp Zip sẽ không bù lại bằng lớp ZipPackage. Các tệp được tạo bằng ZipPackage sẽ giúp bạn trở nên tốt. – Craig

0

Trông như Windows chỉ có thể cho phép bạn làm this ...

Đáng tiếc là tôi không nghĩ rằng bạn đang đi để có được xung quanh bắt đầu một quá trình riêng biệt, trừ khi bạn đi đến một thành phần của bên thứ ba.

4

Đối với ứng dụng .NET 2.0, tôi đã sử dụng SharpZipLib. Dễ sử dụng và nguồn mở.

+2

Tôi có thể không sử dụng libs của bên thứ 3. –

+11

Shoud đã đọc kỹ hơn một chút.SharpZipLib vẫn là một thư viện tốt đẹp cho những gì nó có giá trị. –

+0

Bạn có thể tìm các mẫu ở đây: https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples – Spawnrider

11

Tôi đã ở trong tình huống tương tự, muốn .NET thay vì thư viện của bên thứ ba. Như một áp phích khác được đề cập ở trên, chỉ cần sử dụng lớp ZipPackage (được giới thiệu trong .NET 3.5) là không đủ. Có một tệp bổ sung PHẢI được bao gồm trong kho lưu trữ để ZipPackage hoạt động. Nếu tệp này được thêm vào, thì gói ZIP kết quả có thể được mở trực tiếp từ Windows Explorer - không vấn đề gì.

Tất cả những gì bạn phải làm là thêm tệp [Content_Types] .xml vào thư mục gốc của tệp lưu trữ bằng nút "Mặc định" cho mọi tiện ích tệp bạn muốn bao gồm. Sau khi thêm vào, tôi có thể duyệt gói từ Windows Explorer hoặc giải nén chương trình và đọc nội dung của nó.

Thông tin thêm về [Content_Types] tập tin .xml có thể được tìm thấy ở đây: http://msdn.microsoft.com/en-us/magazine/cc163372.aspx

Đây là một mẫu của [Content_Types] .xml (phải được đặt tên chính xác) file:

<?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> 

và C# để tạo một tập tin 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)); 
      } 
     } 
    } 

Lưu ý:

+11

Mẫu đẹp, nhưng nó không tạo tệp ZIP. Nó giải nén một tập tin hiện có. –

+0

+1 Đối với tham chiếu System.IO.Compression –

216

Làm thế nào tôi có thể programatically (C#) ZIP một tập tin (trong Windows) mà không sử dụng bất kỳ thư viện của bên thứ ba?

Nếu sử dụng khung 4.5+, hiện có các lớp ZipArchiveZipFile.

using (ZipArchive zip = ZipFile.Open("test.zip", ZipArchiveMode.Create)) 
{ 
    zip.CreateEntryFromFile(@"c:\something.txt", "data/path/something.txt"); 
} 

Bạn cần phải thêm tham chiếu đến:

  • System.IO.Compression
  • System.IO.Compression.FileSystem

Đối nhắm mục tiêu NET lõi net46, bạn cần thêm phụ thuộc cho

  • System.IO.Compression
  • System.IO.Compression.ZipFile

Ví dụ project.json:

"dependencies": { 
    "System.IO.Compression": "4.1.0", 
    "System.IO.Compression.ZipFile": "4.0.1" 
}, 

"frameworks": { 
    "net46": {} 
} 

Đối với NET Lõi 2.0, chỉ cần thêm một tuyên bố sử dụng đơn giản là tất cả những gì cần thiết:

  • sử dụng System.IO.Compression;
+3

Làm thế nào điều này không nhận được nhiều upvotes hơn? Đó là câu trả lời trực tiếp duy nhất. –

+9

Bởi vì câu hỏi là năm tuổi, trong khi câu trả lời này chỉ là hai tháng tuổi. Derp :-P – Heliac

+3

@heliac vẫn là Stackieflow thingie nên là một câu hỏi và câu trả lời kho và trong tinh thần câu trả lời tốt nhất shoudl được trên đầu trang ... (damn, tôi biết điều này không hoạt động) – Offler

1

Dựa tắt Simon McKenzie của câu trả lời to this question, tôi muốn đề nghị sử dụng một cặp các phương pháp như thế này:

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); 
    } 
} 
3
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"); 
    } 
Các vấn đề liên quan