J'essaie de créer un fichier Zip dans .NET 4.5 (System.IO.Compression) à partir d'une série de tableaux d'octets. Par exemple, à partir d'une API que j'utilise, je me retrouve avec un List<Attachment>
et chaque Attachment
possède une propriété appelée Body
qui est un byte[]
. Comment puis-je parcourir cette liste et créer un fichier Zip contenant chaque pièce jointe?
En ce moment, j'ai l'impression que je devrais écrire chaque pièce jointe sur le disque et créer le fichier Zip à partir de cela.
//This is great if I had the files on disk
ZipFile.CreateFromDirectory(startPath, zipPath);
//How can I create it from a series of byte arrays?
Après un peu plus de jeu et de lecture, j'ai pu comprendre cela. Voici comment vous pouvez créer un fichier Zip (archive) avec plusieurs fichiers sans écrire de données temporaires sur le disque:
using (var compressedFileStream = new MemoryStream())
//Create an archive and store the stream in memory.
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, false)) {
foreach (var caseAttachmentModel in caseAttachmentModels) {
//Create a Zip entry for each attachment
var zipEntry = zipArchive.CreateEntry(caseAttachmentModel.Name);
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(caseAttachmentModel.Body))
using (var zipEntryStream = zipEntry.Open()) {
//Copy the attachment stream to the Zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
}
return new FileContentResult(compressedFileStream.ToArray(), "application/Zip") { FileDownloadName = "Filename.Zip" };
}
Il s'agit d'une variante de la grande réponse acceptée publiée par le PO. Cependant, c'est pour WebForms au lieu de MVC. Je travaille avec l'hypothèse que caseAttachmentModel.Body est un octet []
Essentiellement, tout est le même, sauf avec une méthode supplémentaire qui envoie le Zip en tant que réponse.
using (var compressedFileStream = new MemoryStream()) {
//Create an archive and store the stream in memory.
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false)) {
foreach (var caseAttachmentModel in caseAttachmentModels) {
//Create a Zip entry for each attachment
var zipEntry = zipArchive.CreateEntry(caseAttachmentModel.Name);
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(caseAttachmentModel.Body)) {
using (var zipEntryStream = zipEntry.Open()) {
//Copy the attachment stream to the Zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
}
}
}
sendOutZIP(compressedFileStream.ToArray(), "FileName.Zip");
}
private void sendOutZIP(byte[] zippedFiles, string filename)
{
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/x-compressed";
Response.Charset = string.Empty;
Response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
Response.BinaryWrite(zippedFiles);
Response.OutputStream.Flush();
Response.OutputStream.Close();
Response.End();
}
Je voudrais également souligner que les conseils donnés par @Levi Fuller sur les références dans la réponse acceptée sont parfaits!
GZipStream et DeflateStream semblent vous permettre d'utiliser des tableaux à vapeur/octets pour résoudre votre problème, mais peut-être pas avec un format de fichier de compression utilisable par la plupart des utilisateurs. (c'est-à-dire que votre fichier aurait une extension .gz) Si ce fichier est uniquement utilisé en interne, cela pourrait être correct.
Je ne sais pas comment vous pourriez faire un Zip en utilisant les bibliothèques de Microsoft, mais je me souviens de cette bibliothèque prenant en charge le genre de choses que vous pourriez trouver utiles: http://sevenzipsharp.codeplex.com/
Il est sous licence LGPL.