web-dev-qa-db-fra.com

ZipArchive donne une erreur de fin de données corrompue inattendue

J'essaie de créer un flux Zip à la volée avec des données de tableau d'octets et de le faire télécharger via mon action MVC.

Mais le fichier téléchargé donne toujours l'erreur corrompue suivante lorsqu'il est ouvert dans Windows.

enter image description here

Et cette erreur quand j'essaye d'extraire de 7z

enter image description here

Mais notez que les fichiers extraits du 7z ne sont pas corrompus.

J'utilise ZipArchive et voici mon code.

    private byte[] GetZippedPods(IEnumerable<POD> pods, long consignmentID)
    {
        using (var zipStream = new MemoryStream())
        {
            //Create an archive and store the stream in memory.                
            using (var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
            {
                int index = 1;
                foreach (var pod in pods)
                {                        
                    var zipEntry = zipArchive.CreateEntry($"POD{consignmentID}{index++}.png", CompressionLevel.NoCompression);                       
                    using (var originalFileStream = new MemoryStream(pod.ByteData))
                    {
                        using (var zipEntryStream = zipEntry.Open())
                        {
                            originalFileStream.CopyTo(zipEntryStream);
                        }
                    }
                }
                return zipStream.ToArray();
            }
        }
    }

    public ActionResult DownloadPOD(long consignmentID)
    {
        var pods = _consignmentService.GetPODs(consignmentID);
        var fileBytes = GetZippedPods(pods, consignmentID);
        return File(fileBytes, MediaTypeNames.Application.Octet, $"PODS{consignmentID}.Zip");
    }

Qu'est-ce que je fais de mal ici.

Toute aide serait très appréciée car je lutte avec cela pendant une journée entière.

Merci d'avance

18
Faraj Farook

Déplacez zipStream.ToArray() en dehors de zipArchive à l'aide de.

La raison de votre problème est que le flux est mis en mémoire tampon. Il y a plusieurs façons de le gérer:

  • Vous pouvez définir la propriété AutoFlush du flux sur true.
  • Vous pouvez appeler manuellement .Flush() sur le flux.

Ou, puisque c'est MemoryStream et que vous utilisez .ToArray(), vous pouvez simplement autoriser le flux à être fermé/supprimé en premier (ce que nous avons fait en le déplaçant en dehors de using).

27
John

Je Dispose ZipArchive Et erreur résolue

 public static byte[] GetZipFile(Dictionary<string, List<FileInformation>> allFileInformations)
    {

        MemoryStream compressedFileStream = new MemoryStream();
        //Create an archive and store the stream in memory.
        using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, true))
        {
            foreach (var fInformation in allFileInformations)
            {
                var files = allFileInformations.Where(x => x.Key == fInformation.Key).SelectMany(x => x.Value).ToList();
                for (var i = 0; i < files.Count; i++)
                {
                    ZipArchiveEntry zipEntry = zipArchive.CreateEntry(fInformation.Key + "/" + files[i].FileName);

                    var caseAttachmentModel = Encoding.UTF8.GetBytes(files[i].Content);

                    //Get the stream of the attachment
                    using (var originalFileStream = new MemoryStream(caseAttachmentModel))
                    using (var zipEntryStream = zipEntry.Open())
                    {
                        //Copy the attachment stream to the Zip entry stream
                        originalFileStream.CopyTo(zipEntryStream);
                    }
                }
            }
            //i added this line 
            zipArchive.Dispose();

            return compressedFileStream.ToArray();
        }
    }

public void SaveZipFile(){
        var zipFileArray = Global.GetZipFile(allFileInformations);
        var zipFile = new MemoryStream(zipFileArray);
        FileStream fs = new FileStream(path + "\\111.Zip", 
        FileMode.Create,FileAccess.Write);
        zipFile.CopyTo(fs);
        zipFile.Flush();
        fs.Close();
        zipFile.Close();
}
2
Afshin Razaghi

J'avais également des problèmes avec cela et j'ai trouvé que mon problème n'était pas la génération de l'archive elle-même mais plutôt la façon dont je traitais ma demande GET dans AngularJS.

Ce message m'a aidé: comment télécharger un fichier Zip en utilisant angulaire

La clé ajoutait responseType: 'arraybuffer' à mon appel $ http.

factory.serverConfigExportZIP = function () {
    return $http({
        url: dataServiceBase + 'serverConfigExport',
        method: "GET",
        responseType: 'arraybuffer'
    })
};
0
Ian