c# - जिप फाइल स्ट्रीम से बनाकर डाउनलोड करें




asp.net zip stream dotnetzip (8)

मेरे पास एक DataTable है जिसे मैं इसे DmlNetZip का उपयोग करके xml में बदलना और फिर इसे ज़िप करना चाहता हूं। अंत में उपयोगकर्ता इसे Asp.Net वेबपेज के माध्यम से डाउनलोड कर सकते हैं। नीचे में मेरा कोड

    dt.TableName = "Declaration";

    MemoryStream stream = new MemoryStream();
    dt.WriteXml(stream);

    ZipFile zipFile = new ZipFile();
    zipFile.AddEntry("Report.xml", "", stream);
    Response.ClearContent();
    Response.ClearHeaders();
    Response.AppendHeader("content-disposition", "attachment; filename=Report.zip");

    zipFile.Save(Response.OutputStream);
    //Response.Write(zipstream);
    zipFile.Dispose();

ज़िप फ़ाइल में xml फ़ाइल खाली है।


Answers

ठीक। ऐसा लगता नहीं है कि हम यहाँ बहुत दूर हो रहे हैं इसलिए आपको इसे थोड़ा और डीबग करना शुरू करना होगा।

अपडेट करें कि आप निम्नलिखित करने के लिए कोड हैं:

dt.WriteXml(stream);
stream.Seek(0, SeekOrigin.Begin);
File.WriteAllBytes("c:\test.xml", stream.GetBuffer());

देखें कि क्या आपके पास एक वैध XML फ़ाइल है। यदि आप ऐसा करते हैं तो अपने ZIPFile के साथ भी ऐसा ही करें। इसे स्थानीय फ़ाइल में सहेजें। देखें कि क्या यह वहाँ है, आपकी xml फ़ाइल है और आपकी xml फ़ाइल में सामग्री है।

यदि वह काम करता है, तो प्रतिक्रिया के रूप में सिर्फ मेमोरी स्ट्रीम भेजने का प्रयास करें, देखें कि क्या काम करता है।

फिर आपको समस्या को और अधिक ट्रैक करने में सक्षम होना चाहिए।


जिस स्ट्रीम को आप वापस भी कर रहे हैं उसे दोबारा चेक करें। नीचे अपने उदाहरण में

zipFile.Save(Response.OutputStream);
Response.Write(zipstream);
zipFile.Dispose();

आप सहेजें विधि का उपयोग करके अपनी प्रतिक्रिया स्ट्रीम में zipFile को सहेज रहे हैं, लेकिन फिर आप zipstream चर के साथ Response.Write () भी कॉल कर रहे हैं। ज़िपस्ट्रीम क्या है? जांचें कि यह एक खाली स्ट्रीम नहीं है।


स्ट्रीम से जिप फाइल बनाकर डाउनलोड करें। नीचे कोड है।

FileStream stream=File.OpenRead(@"D:\FileDownLoad\DeskTop\1.txt");
MemoryStream MS=new MemoryStream();

ZipOutputStream zipOutputStream = new ZipOutputStream(MS);
zipOutputStream.SetLevel(9);
ZipEntry entry = new ZipEntry("1.txt");
zipOutputStream.PutNextEntry(entry);

byte[] buffer = new byte[stream.Length];
int byteRead = 0;

while ((byteRead = stream.Read(buffer, 0, buffer.Length)) > 0) 
    zipOutputStream.Write(buffer, 0, byteRead);

    zipOutputStream.IsStreamOwner = false;
    stream.Close();
    zipOutputStream.Close();
    MS.Position = 0;

    Response.ContentType = "application/application/octet-stream";
    Response.AppendHeader("content-disposition", "attachment; filename=\"Download.zip\"");
    Response.BinaryWrite(MS.ToArray());

२ बातें। सबसे पहले, यदि आपके पास कोड डिज़ाइन है, तो आपको प्रविष्टि में लिखने से पहले मेमोरीस्ट्रीम पर एक सीक () करना होगा।

dt.TableName = "Declaration"; 

MemoryStream stream = new MemoryStream(); 
dt.WriteXml(stream); 
stream.Seek(0,SeekOrigin.Begin);   // <-- must do this after writing the stream!

using (ZipFile zipFile = new ZipFile())
{
  zipFile.AddEntry("Report.xml", "", stream); 
  Response.ClearContent(); 
  Response.ClearHeaders(); 
  Response.AppendHeader("content-disposition", "attachment; filename=Report.zip"); 

  zipFile.Save(Response.OutputStream); 
}

यहां तक ​​कि अगर आप इस डिज़ाइन को रखते हैं, तो मैं एक प्रयोग () खंड का सुझाव दूंगा, जैसा कि मैंने दिखाया है, और जैसा कि सभी DotNetZip उदाहरणों में वर्णित है, कॉलिंग डिस्पोज़ () के बदले में। असफलताओं का सामना करते हुए उपयोग () खंड अधिक विश्वसनीय है।

अब आप सोच सकते हैं, AddEntry () को कॉल करने से पहले मेमोरीस्ट्रीम में तलाश करना क्यों आवश्यक है? कारण है, AddEntry () को उन कॉलर्स का समर्थन करने के लिए डिज़ाइन किया गया है जो एक स्ट्रीम पास करते हैं जहां स्थिति महत्वपूर्ण है। उस स्थिति में, कॉल करने वाले को स्ट्रीम से वर्तमान स्थिति का उपयोग करके स्ट्रीम से पढ़ने के लिए प्रवेश डेटा की आवश्यकता होती है । AddEntry () उस का समर्थन करता है। इसलिए, AddEntry () को कॉल करने से पहले स्ट्रीम में स्थिति सेट करें।

लेकिन, बेहतर विकल्प यह है कि अपने कोड को AddEntry () के अधिभार का उपयोग करने के लिए संशोधित करें जो एक WriteDelegate स्वीकार करता है । यह विशेष रूप से ज़िप फ़ाइलों में डेटासेट जोड़ने के लिए डिज़ाइन किया गया था। आपका मूल कोड डेटासेट को मेमोरी स्ट्रीम में लिखता है, फिर स्ट्रीम पर खोज करता है, और स्ट्रीम की सामग्री को ज़िप में लिखता है। यदि आप एक बार डेटा लिखते हैं, तो यह तेज और आसान है, जो कि WriteDelegate आपको करने की अनुमति देता है। कोड इस तरह दिखता है:

dt.TableName = "Declaration"; 
Response.ClearContent(); 
Response.ClearHeaders(); 
Response.ContentType = "application/zip";
Response.AppendHeader("content-disposition", "attachment; filename=Report.zip"); 

using(Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile())
{
    zipFile.AddEntry("Report.xml", (name,stream) => dt.WriteXml(stream) );
    zipFile.Save(Response.OutputStream); 
}

यह डेटासेट सीधे zipfile में संपीड़ित स्ट्रीम में लिखता है। बहुत ही कुशल! कोई डबल-बफ़रिंग नहीं। अनाम प्रतिनिधि को ZipFile.Save () के समय कहा जाता है। केवल एक लेखन (+ कंप्रेस) किया जाता है।


आपने zipFile बंद क्यों नहीं किया, मैं इसे एक क्लॉज में zipFile , जो कि zipFile लिए कहा जा सकता है? इसके अलावा, मुझे लगता है कि एक DataTable है ... अगर वहाँ पंक्तियाँ हैं, यह देखने के लिए त्रुटि जाँच में डाल दिया है ...

    dt.TableName = "Declaration"; 

    if (dt.Rows != null && dt.Rows.Count >= 1){
      using (MemoryStream stream = new MemoryStream()){
         dt.WriteXml(stream); 

         // Thanks Cheeso/Mikael
         stream.Seek(0, SeekOrigin.Begin);
         //

         using (ZipFile zipFile = new ZipFile()){
             zipFile.AddEntry("Report.xml", "", stream); 
             Response.ClearContent(); 
             Response.ClearHeaders(); 
             Response.AppendHeader("content-disposition", "attachment; filename=Report.zip"); 

             //zipFile.Save(Response.OutputStream); 
             zipFile.Save(stream);

             // Commented this out
             /*
               Response.Write(zipstream); // <----- Where did that come from?
             */
          }
          Response.Write(stream);
       } 
    }
    // No rows...don't bother...

संपादित करें: इसे फिर से देखा, और यह महसूस करते हुए कि Ionic.Ziplib से Ionic.Ziplib का उपयोग किया गया था, मैंने zipFile.Save(Response.OutputStream); बजाय कोड को थोड़ा बदल दिया zipFile.Save(Response.OutputStream); मैंने zipFile.Save(stream); उपयोग किया zipFile.Save(stream); MemoryStream क्लास के stream उदाहरण का उपयोग करके और Response.Write(stream); का उपयोग करके इसे लिखें Response.Write(stream);

# 2 संपादित करें: स्पष्ट दोष को इंगित करने के लिए चेसो + मिकेल को धन्यवाद - मैंने इसे एक मील से चूक दिया और उनकी टिप्पणी को तब तक नहीं समझा जब तक मुझे एहसास नहीं हुआ कि धारा अंत में थी ...


क्या आपने ज़िपिंग से पहले स्ट्रीम को फ्लश करने की कोशिश की है?

dt.WriteXml(stream);
stream.Flush();
ZipFile zipFile = new ZipFile();

एक कंटेंट टाइप हेडर जोड़ें:

Response.ContentType = "application/zip";

यह ब्राउज़रों को यह पता लगाने की अनुमति देगा कि आप क्या भेज रहे हैं।


public HttpResponseMessage GetItemsInZip(int id)
    {           
            var itemsToWrite = // return array of objects based on id;

            // create zip file stream
            MemoryStream archiveStream = new MemoryStream();
            using (ZipArchive archiveFile = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
            {
                foreach (var item in itemsToWrite)
                {
                    // create file streams
                    // add the stream to zip file

                    var entry = archiveFile.CreateEntry(item.FileName);
                    using (StreamWriter sw = new StreamWriter(entry.Open()))
                    {
                        sw.Write(item.Content);
                    }
                }
            }

            // return the zip file stream to http response content                
            HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.OK);                
            responseMsg.Content = new ByteArrayContent(archiveStream.ToArray());
            archiveStream.Dispose();
            responseMsg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "test.zip" };
            responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");

            return responseMsg;          
    }

एमवीसी 5 के साथ प्रयुक्त फ्रेमवर्क .नेट 4.6.1





c# asp.net zip stream dotnetzip