Wenn ein Benutzer auf eine bestimmte Schaltfläche klickt, müssen einige Dateien in einer ZIP-Datei archiviert und versendet werden. Die Dateien selbst werden von einem dritten Teil generiert und ich habe nur die URLs. Ich habe das teilweise geschafft, aber ich habe einige Probleme.Eine Zip-Datei senden, während sie erstellt wird
Erstens, wenn es viele Dateien zu zippen gibt, ist die Serverantwort langsam, da sie zuerst die Zip-Datei erstellt und dann sendet. Es kann sogar nach einer Weile abstürzen (insbesondere bekomme ich den Fehler "Überlauf oder Unterlauf in der arithmetischen Operation.").
Zweitens, jetzt wird die Datei nur gesendet, sobald das Zip-Archiv abgeschlossen ist. Ich möchte, dass der Download sofort beginnt. Sobald der Benutzer auf "Speichern" aus dem Dialog geklickt hat, beginnen die Daten zu senden und senden weiter, während die Zip-Datei "on the fly" erstellt wird. Ich habe diese Funktion auf einigen Websites gesehen, zum Beispiel: http://download.muuto.com/
Problem ist, ich kann nicht herausfinden, wie das geht.
Ich habe Teile des Codes von dieser Frage verwendet: Creating a dynamic zip of a bunch of URLs on the fly Und aus diesem Blog-Eintrag: http://dejanstojanovic.net/aspnet/2015/march/generate-zip-file-on-the-fly-in-aspnet-mvc-application/
Die Zip-Datei selbst erstellt und zurückgegeben in einer ASP.NET MVC-Controller-Methode. Hier ist mein Code:
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace MyProject.Controllers
{
public class MyController : Controller
{
public ActionResult DownloadFiles()
{
var files = SomeFunction();
byte[] buffer = new byte[4096];
var baseOutputStream = new MemoryStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(baseOutputStream);
zipOutputStream.SetLevel(0); //0-9, 9 being the highest level of compression
zipOutputStream.UseZip64 = UseZip64.Off;
zipOutputStream.IsStreamOwner = false;
foreach (var file in files)
{
using (WebClient wc = new WebClient())
{
// We open the download stream of the file
using (Stream wcStream = wc.OpenRead(file.Url))
{
ZipEntry entry = new ZipEntry(ZipEntry.CleanName(file.FileName));
zipOutputStream.PutNextEntry(entry);
// As we read the stream, we add its content to the new zip entry
int count = wcStream.Read(buffer, 0, buffer.Length);
while (count > 0)
{
zipOutputStream.Write(buffer, 0, count);
count = wcStream.Read(buffer, 0, buffer.Length);
if (!Response.IsClientConnected)
{
break;
}
}
}
}
}
zipOutputStream.Finish();
zipOutputStream.Close();
// Set position to 0 so that cient start reading of the stream from the begining
baseOutputStream.Position = 0;
// Set custom headers to force browser to download the file instad of trying to open it
return new FileStreamResult(baseOutputStream, "application/x-zip-compressed")
{
FileDownloadName = "Archive.zip"
};
}
}
}
Mögliches Duplikat [in eine Zip-Datei über HTTP-Streaming. net mit SharpZipLib] (http://stackoverflow.com/questions/626196/streaming-a-zip-file-over-http-in-net-with-sharpziplib) –
Definitiv verwandt (dasselbe Ziel), aber nicht doppelt: I Ich versuche es von einem MVC-Controller zu machen, was ein anderer Ansatz ist. Ich habe versucht, 'BufferOutput = false' auf verschiedene Arten zu verwenden, aber es scheint sich nicht viel zu ändern. – Ogier
Es ist nicht anders. Sie können ein 'FileResult' zurückgeben, das einen Stream als Parameter akzeptiert –