Comment puis-je compresser à la volée et diffuser sur Response.Output en temps réel?
Je suis en train d'utiliser le code suivant: j'ai une corruption de fichier zip. Pourquoi?
Les noms de fichiers semblent OK. Peut-être qu'ils ne sont pas des noms relatifs, et c'est ça le problème?
private void trySharpZipLib(ArrayList filesToInclude)
{
//Response header
Response.Clear();
Response.ClearHeaders();
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.StatusCode = 200; //http://community.icsharpcode.net/forums/p/6946/20138.aspx
long zipSize = calculateZipSize(filesToInclude);
string contentValue =
string.Format("attachment; filename=moshe.zip;"
); //+ " size={0}", zipSize);
Response.ContentType = "application/octet-stream"; //"application/zip";
Response.AddHeader("Content-Disposition", contentValue);
Response.Flush();
using (ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream) )
{
zipOutputStream.SetLevel(0);
foreach (string f in filesToInclude)
{
string filename = Path.Combine(Server.MapPath("."), f);
using (FileStream fs = File.OpenRead(filename))
{
ZipEntry entry =
new ZipEntry(ZipEntry.CleanName(filename))
{
DateTime = File.GetCreationTime(filename),
CompressionMethod = CompressionMethod.Stored,
Size = fs.Length
};
zipOutputStream.PutNextEntry(entry);
byte[] buffer = new byte[fs.Length];
//write to zipoutStream via buffer.
//The zipoutStream is directly connected to Response.Output (in the constructor)
ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fs, zipOutputStream, buffer);
Response.Flush(); //for immediate response to user
} //.. using file stream
}//.. each file
}
Response.Flush();
Response.End();
}
source d'informationauteur
Vous devez vous connecter pour publier un commentaire.
Garçon, c'est beaucoup de code! Votre travail serait plus simple à l'aide de DotNetZip. En supposant un client HTTP 1.1, cela fonctionne:
Si vous voulez le mot de passe crypter le fichier zip, puis avant l'AddFiles(), insérez ces lignes:
Si vous voulez une archive auto-extractible, puis remplacez zip.Save() avec zip.SaveSelfExtractor().
Additif; certaines personnes m'ont commenté que DotNetZip est "pas bon" parce qu'il crée l'ensemble du ZIP dans la mémoire avant de les diffuser. Ce n'est pas le cas. Lorsque vous appelez AddFilesla bibliothèque crée une liste d'entrées - des objets qui représentent l'état des choses à être compressé vers le haut. Il n'y a pas de compression ou de chiffrement jusqu'à l'appel à Enregistrer. Si vous spécifiez un flux de données de la Save (), puis tous les octets compressés obtenir en streaming directement au client.
Dans le SharpZipLib modèle, il est possible de créer une entrée, puis de le transmettre, puis de créer une autre entrée, et le flux, et ainsi de suite. Avec DotNetZip votre application crée la liste complète des entrées d'abord, puis les ruisseaux. Aucune approche est nécessairement "plus vite" que les autres, même si, pour de longues listes de fichiers, dire 30 000 personnes, le temps de premier octet sera plus rapide avec SharpZipLib. D'autre part, je ne recommanderais pas de créer dynamiquement des fichiers zip avec 30 000 entrées.
MODIFIER
Certaines personnes ont le cas où ils ont zip contenu qui est "essentiellement la même" pour tous les utilisateurs, mais il ya un couple de fichiers qui sont différentes pour chacun. DotNetZip est bon à cette, trop. Vous pouvez le lire dans une archive zip à partir d'un système de fichiers de fichiers, mise à jour de quelques entrées (ajouter un peu d', de supprimer quelques-uns, etc), puis sur enregistrer pour la Réponse.OutputStream. Dans ce cas DotNetZip de ne pas re-compresser ou re-chiffrer toutes les entrées que vous n'avez pas changé. Beaucoup plus rapide.
Bien sûr DotNetZip est pour tout .NET application, non seulement ASP.NET. De sorte que vous pouvez enregistrer n'importe quel flux.
Si vous voulez plus d'info, consultez le site ou poster sur le dotnetzip forums.
Pas tout à fait sûr de savoir comment le faire dans ASP.NET (ne les avez pas essayé avant), mais en général, si le client HTTP prend en charge HTTP v1.1 (comme indiqué par la version de sa demande), le serveur peut envoyer un "Transfer-Encoding' en-tête de réponse précise 'en bloc', et ensuite envoyer les données de réponse à l'aide de plusieurs blocs de données à mesure qu'ils deviennent disponibles. Cela permet la diffusion en temps réel de données où vous ne connaissez pas la finale de la taille des données à l'avance et ne peut donc pas définir le "Content-Length' en-tête de réponse). Jetez un oeil à La RFC 2616 la Section 3.6 pour plus de détails.
Pour ceux qui auraient raté la ZipOutputStream de SharpZipLib, voici un code simple qui rend possible l'utilisation de DotNetZip la "régulière .NET flux".
Toutefois, prenez note qu'il est inefficace par rapport à un vrai à la volée solution de streaming comme SharpZipLib n', car elle utilise un interne MemoryStream avant l'appel de la DotNetZip.Save() de la fonction. Mais malheureusement, SharpZibLib ne fait pas de sport EAS de Chiffrement encore (et certainement jamais). Espérons que Cheeso permettra d'ajouter cette fonctionnalité dans dotNetZip tout moment bientôt ? 😉
Essayez d'ajouter l'en-tête suivant.
Je sais que c'est en me faisant les questions de avant de.
Edit:
Ces 2 autres peut aider ainsi:
Avez-vous essayé de vider le ZipOutputStream avant de rincer la réponse?
Vous pouvez enregistrer le zip sur le client et de le tester dans un utilitaire zip?
Necromancing.
Voici comment c'est fait correctement, à l'aide de fermetures, à commencer par DotNetZip v1.9+ tel que recommandé par Cheeso dans les commentaires:
Et la VB.NET variante, dans le cas où quelqu'un en a besoin (veuillez noter que ceci est juste un test; en réalité, il serait appelé avec différents in_contract_uid et in_premise_uid pour chaque étape de la boucle):