Besoin de conditionner dynamiquement certains fichiers dans un fichier .Zip pour créer un package SCORM, tout le monde sait-il comment cela peut être fait avec du code? Est-il possible de construire dynamiquement la structure de dossiers à l'intérieur du fichier .Zip?
Vous n'êtes plus obligé d'utiliser une bibliothèque externe. System.IO.Packaging a des classes qui peuvent être utilisées pour déposer du contenu dans un fichier Zip. Ce n'est pas simple, cependant. Voici un article de blog avec un exemple (son à la fin; Dig pour cela).
Le lien n'est pas stable, voici donc l'exemple fourni par Jon dans l'article.
using System;
using System.IO;
using System.IO.Packaging;
namespace ZipSample
{
class Program
{
static void Main(string[] args)
{
AddFileToZip("Output.Zip", @"C:\Windows\Notepad.exe");
AddFileToZip("Output.Zip", @"C:\Windows\System32\Calc.exe");
}
private const long BUFFER_SIZE = 4096;
private static void AddFileToZip(string zipFilename, string fileToAdd)
{
using (Package Zip = 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);
}
}
}
}
private static void CopyStream(System.IO.FileStream inputStream, 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;
}
}
}
}
DotNetZip est agréable pour cela. Exemple de travail
Vous pouvez écrire le zip directement dans Response.OutputStream. Le code ressemble à ceci:
Response.Clear();
Response.BufferOutput = false; // for large files...
System.Web.HttpContext c= System.Web.HttpContext.Current;
String ReadmeText= "Hello!\n\nThis is a README..." + DateTime.Now.ToString("G");
string archiveName= String.Format("archive-{0}.Zip",
DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
Response.ContentType = "application/Zip";
Response.AddHeader("content-disposition", "filename=" + archiveName);
using (ZipFile Zip = new ZipFile())
{
// filesToInclude is an IEnumerable<String>, like String[] or List<String>
Zip.AddFiles(filesToInclude, "files");
// Add a file from a string
Zip.AddEntry("Readme.txt", "", ReadmeText);
Zip.Save(Response.OutputStream);
}
// Response.End(); // no! See http://stackoverflow.com/questions/1087777
Response.Close();
DotNetZip est gratuit.
Vous pouvez jeter un oeil à SharpZipLib . Et voici un échantillon .
DotNetZip est très facile à utiliser ... Créer des fichiers Zip dans ASP.Net
J'ai utilisé un composant gratuit de chilkat pour cela: http://www.chilkatsoft.com/Zip-dotnet.asp . Fait à peu près tout ce dont j'ai besoin, mais je ne suis pas sûr de pouvoir construire la structure de fichiers de manière dynamique.
Capable de faire cela en utilisant DotNetZip. vous pouvez le télécharger à partir du gestionnaire de paquets Nuget de Visual Studio ou directement via DotnetZip . puis essayez ci-dessous le code,
/// <summary>
/// Generate Zip file and save it into given location
/// </summary>
/// <param name="directoryPath"></param>
public void CreateZipFile(string directoryPath )
{
//Select Files from given directory
List<string> directoryFileNames = Directory.GetFiles(directoryPath).ToList();
using (ZipFile Zip = new ZipFile())
{
Zip.AddFiles(directoryFileNames, "");
//Generate Zip file folder into loation
Zip.Save("C:\\Logs\\ReportsMyZipFile.Zip");
}
}
Si vous souhaitez télécharger le fichier sur le client, utilisez le code ci-dessous.
/// <summary>
/// Generate Zip file and download into client
/// </summary>
/// <param name="directoryPath"></param>
/// <param name="respnse"></param>
public void CreateZipFile(HttpResponse respnse,string directoryPath )
{
//Select Files from given directory
List<string> directoryFileNames = Directory.GetFiles(directoryPath).ToList();
respnse.Clear();
respnse.BufferOutput = false;
respnse.ContentType = "application/Zip";
respnse.AddHeader("content-disposition", "attachment; filename=MyFiles.Zip");
using (ZipFile Zip = new ZipFile())
{
Zip.CompressionLevel = CompressionLevel.None;
Zip.AddFiles(directoryFileNames, "");
Zip.Save(respnse.OutputStream);
}
respnse.flush();
}
Si vous utilisez .NET Framework 4.5 ou une version plus récente, vous pouvez éviter les bibliothèques tierces et utiliser la classe native System.IO.Compression.ZipArchive
.
Voici un exemple de code rapide utilisant un MemoryStream et deux tableaux d’octets représentant deux fichiers:
byte[] file1 = GetFile1ByteArray();
byte[] file2 = GetFile2ByteArray();
using (MemoryStream ms = new MemoryStream())
{
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
var zipArchiveEntry = archive.CreateEntry("file1.txt", CompressionLevel.Fastest);
using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(file1, 0, file1.Length);
zipArchiveEntry = archive.CreateEntry("file2.txt", CompressionLevel.Fastest);
using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(file2, 0, file2.Length);
}
return File(ms.ToArray(), "application/Zip", "Archive.Zip");
}
Vous pouvez l'utiliser dans un contrôleur MVC en renvoyant une ActionResult
: sinon, si vous devez créer physiquement l'archive Zip, vous pouvez soit conserver la MemoryStream
sur disque, soit la remplacer entièrement par une FileStream
.
Pour plus d'informations sur ce sujet, vous pouvez également lire cet article sur mon blog.
Créer un fichier Zip "à la volée" se ferait avec notre composant Rebex Zip .
L'exemple suivant le décrit complètement, y compris la création d'un sous-dossier:
// prepare MemoryStream to create Zip archive within
using (MemoryStream ms = new MemoryStream())
{
// create new Zip archive within prepared MemoryStream
using (ZipArchive Zip = new ZipArchive(ms))
{
// add some files to Zip archive
Zip.Add(@"c:\temp\testfile.txt");
Zip.Add(@"c:\temp\innerfile.txt", @"\subfolder");
// clear response stream and set the response header and content type
Response.Clear();
Response.ContentType = "application/Zip";
Response.AddHeader("content-disposition", "filename=sample.Zip");
// write content of the MemoryStream (created Zip archive) to the response stream
ms.WriteTo(Response.OutputStream);
}
}
// close the current HTTP response and stop executing this page
HttpContext.Current.ApplicationInstance.CompleteRequest();