Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating zip in c# with System.IO.Packaging

I am trying to create zip file dynamically on the server that includes photos from online services. But when I try to open the file, WinRar sais the the file is unknown format or damaged.

this is the code:

MemoryStream stream = new MemoryStream();
Package package = ZipPackage.Open(stream, FileMode.Create, FileAccess.ReadWrite);

foreach (Order o in orders)
{
    o.GetImages();

    Parallel.ForEach(o.Images, (Dictionary<string, object> image) =>
    {
        string imageId = (string)image["ID"];
        int orderId = (int)image["OrderId"];
        string fileName = (string)image["FileName"];
        string url = (string)image["URL"];

        if (string.IsNullOrEmpty(fileName))
        {
            System.Net.WebClient wc = new System.Net.WebClient();
            byte[] data = wc.DownloadData(url);
            MemoryStream ms = new MemoryStream(data);
            ms.Write(data, 0, data.Length);

            string ext;

            switch(wc.ResponseHeaders["Content-Type"])
            {
                case "image/jpeg":
                case "image/jpg":
                ext = "jpg";
                    break;

                case "image/png":
                    ext = "png";
                    break;

                case "image/gif":
                    ext = "gif";
                    break;

                default :
                    ext = "un";
                    break;
            }

            Uri uri = new Uri("/" + orderId.ToString() + "/" + imageId + "." + ext, UriKind.Relative);

            var part = package.CreatePart(uri, wc.ResponseHeaders["Content-Type"], CompressionOption.NotCompressed);

            var pstream = part.GetStream(FileMode.Open, FileAccess.ReadWrite);

            pstream.Write(data, 0, data.Length);

            var rel = package.CreateRelationship(part.Uri, TargetMode.Internal, "http://example.com/AlbumImage");


        }
    });
}

package.Flush();

byte[] fileBytes = new byte[stream.Length];
stream.Read(fileBytes, 0, Convert.ToInt32(stream.Length));

Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=Orders.zip");
Response.AddHeader("Content-Length", stream.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.BinaryWrite(fileBytes);
Response.End();
like image 888
aikixd Avatar asked Nov 14 '22 20:11

aikixd


1 Answers

It's all about Pack Uris. We also have been beaten by them. Here is working sample for storing two files in zip. Code just copied from our project with removing some private data.

           var dataFilePath = Path.GetFileName(dataFileName);
           var dataFileUri = PackUriHelper.CreatePartUri(new Uri(dataFilePath, UriKind.Relative));
            // Create the Package
            using (var package = Package.Open(filePath, FileMode.Create))
            {
                // Add the diagram view part to the Package
                var pkgPart = package.CreatePart(dataFileUri, MediaTypeNames.Application.Octet);
                var pkgStream = pkgPart.GetStream();

                // Copy the data to the model view part
                // diagramFileName Encoding.Default.GetBytes(text)
                using (var modelStream = new FileStream(dataFileName, FileMode.Open, FileAccess.Read))
                {
                    const int bufSize = 0x1000;
                    var buf = new byte[bufSize];
                    int bytesRead;
                    while ((bytesRead = modelStream.Read(buf, 0, bufSize)) > 0)
                    {
                        pkgStream.Write(buf, 0, bytesRead);
                    }
                }

                // Add a context Part to the Package
                var pkgPartContext = package.CreatePart(ctxUri, MediaTypeNames.Application.Octet);
                var ctxPkgStream = pkgPartContext.GetStream();

                // Copy the data to the context part
                using (var ctxStream = new FileStream(ctxFileName, FileMode.Open, FileAccess.Read))
                {
                    const int bufSize = 0x1000;
                    var buf = new byte[bufSize];
                    int bytesRead;
                    while ((bytesRead = ctxStream.Read(buf, 0, bufSize)) > 0)
                    {
                        ctxPkgStream.Write(buf, 0, bytesRead);
                    }
                }
            }

            // remove tmp files
            File.Delete(ctxFileName);
            File.Delete(dataFileName);
like image 196
Sergey Mirvoda Avatar answered Dec 20 '22 22:12

Sergey Mirvoda