Frage

In den Kommentaren dieser Seite:

http://msdn.microsoft .com / en-us / library / 12s31dhy% 28v = VS.90% 29.aspx

.. es sagt, dass TransmitFile () kann nicht mit UNC-Freigaben verwendet werden. Soweit ich sagen kann, ist dies der Fall; Ich bekomme diese Fehlermeldung in Ereignisprotokoll, wenn ich es versuchen:

TransmitFile failed. File Name: \\myshare1\e$\file.zip, Impersonation Enabled: 0, Token Valid: 1, HRESULT: 0x8007052e

Die vorgeschlagene Alternative ist Writefile () zu verwenden, dies jedoch problematisch ist, weil es die Datei in den Speicher lädt. In meiner Anwendung, die Dateien sind> 200 MB, so wird dies geht nicht maßstab.

Gibt es eine Methode in ASP.NET für Dateien an Benutzer-Streaming, das heißt:

  • skalierbar (nicht gesamte Datei in den Arbeitsspeicher gelesen oder ASP.NET Themen besetzen)
  • arbeitet mit UNC-Aktien

ein Netzlaufwerk als virtuelles Verzeichnis Mapping ist keine Option für uns. Ich möchte auch auf den lokalen Web-Server Kopieren der Datei vermeiden.

Danke

War es hilfreich?

Lösung

Haben Sie versucht, eine IIS vroot mit dem Remote-UNC-Pfad als Home-Verzeichnis einrichten? Wenn es funktioniert, kann dies die einfachste Lösung sein. Sie können immer noch Authentifizierungs Barrieren auf die Dateien (zum Beispiel über ein Httpmodule, oder vielleicht sogar über die Out-of-Box bildet Auth-Modul) erzwingen, aber Sie können auf IIS verlassen effizient den Inhalt zu streamen, sobald Ihre Auth Filter grünes Licht geben.

Eine Einschränkung: das letzte Mal, dass ich IIS in einem UNC-Szenario konfiguriert war vor langer Zeit (1998 !!!) und ich lief in intermittierende Probleme mit Dateien auf dem entfernten Rechner gesperrt werden, so dass Aktualisieren von Dateien manchmal problematisch. Der Umgang mit der Wiederherstellung nach einem Neustart UNC-Servers auch interessant war. Ich gehe davon aus in den 11 Jahren seitdem haben diese Probleme gebügelt worden, aber man kann nie sicher sein!

Ein weiterer Ansatz kann einen Web-Server auf der UNC-Maschine installieren und dann einen Reverse-Proxy-Server auf Ihrem Webserver installieren, wie das neuen IIS7 Anwendungsanforderungen Modul Routing.

Wenn Sie bereit sind, einen Server-Thread zu binden, können Sie den Ansatz in empfohlen verwenden KB812406 , die sich mit Fragen rund um RAM Verbrauch beschäftigt, Timeouts, Client-Trennung, etc. Stellen Sie sicher, dass Antwortpufferung ausschalten!

Die ideale Maximum-Control-Lösung wäre ein „Streaming Httphandler“, wo, anstatt die Ausgabe auf einmal zu senden, Sie einen Stream zu ASP.NET und ASP.NET lassen befassen sich mit den Details über Chunking Ergebnisse zurückgeben könnten an den Client, mit Verbindungsabbrüchen zu tun, usw. Aber ich war nicht in der Lage, eine gute Möglichkeit, dies zu tun zu finden. : - (

Andere Tipps

Etwas, das man versuchen könnte, ist die Netzwerk-Datei mit einem FileStream öffnen und eine Schleife mit einem Stück der Datei zu lesen, überträgt die Brocken (mit Response.Write(Char[], Int32, Int32)), entsorgen Sie die Brocken, und wiederholen, bis die Datei vollständig gelesen wurde .

Sie können die Datei in einem lokalen Verzeichnis schreiben, und haben einen Robocopy Job das Verzeichnis Überwachung der Kopie zu tun.

Da Sie auf dem lokalen Server zu vermeiden, wollen schreiben, aber Sie können setzen einen Server untersuchen wollen (HTTP oder FTP, z) auf dem Zielserver, und Schreiben der Datei auf diesen Dienst.

könnten Sie eine andere IIS-Website einrichten, die auf die UNC-Punkte, dann sie auf dieser anderen Website in die Datei umleiten?

Response.Redirect ( " http://files.somewhere.com/some/file. bla ");

Auf diese Weise wird es in einem separaten Arbeitsprozess ausgeführt werden und haben keinen Einfluss auf Ihre aktuelle Website, und die Dateien werden direkt von IIS bedient werden, die eindeutig am besten ist.

Der eigentliche Fehler, den Sie bekam, war wieder ein Anmeldefehlers auf die Dateifreigabe (die den Benutzer nicht massiv überraschend, wenn man bedenkt IIS ist wahrscheinlich als zu laufen, sowie Sie eine administrative Freigabe zuzugreifen versuchen). Haben Sie versuchten, einen Anteil der Einrichtung, die keine Zugangsbeschränkungen überhaupt hat nur zu prüfen, ob, dass das Problem eher als jede bestimmte Grenze in TransmitFile.

Wenn das behebt es dann Sie auf die Freigabe der einen oder anderen als den aktuellen Benutzer anmelden müssen, oder einen Benutzer ausgeben, die Berechtigungen verfügt.

Es ist auch erwähnenswert, dass nach abit umsah mit Reflektor TransmitFile möglicherweise ohnehin die Datei in den Speicher einzulesen kann am Ende, und das Writefile hat eine andere Version, die einen Booleschen Wert nimmt das anzeigt, ob die Datei in den Speicher zu lesen entscheidet oder nicht (in der Tat geht die Standardwritefile falsch für diesen Parameter). Könnte sich lohnen Sie sich in dem Code Stossen.

würde ich die zweite Stelle Ansatz empfehlen und eine Token-basierte Authentifizierungsmechanismus zu implementieren. Encode einen Authentifizierungs-Cookie in der URL an den Client über Redirect weitergegeben. Dies könnte ein undurchsichtiger Wert sein, der hinter den Kulissen gemeinsam genutzt wird, oder es könnte etwas so einfach wie ein Hash ein geheimen Passwortes und das aktuelle Datum, zum Beispiel.

Ein Projekt, das ich das Hashing verwendet haben. Ein Server erzeugt einen Hash eines gemeinsamen geheimen Passwort und eine Nebenstellennummer. Der zweite Server (die in einem anderen Netzwerk war) nahmen das gleiche Passwort und Erweiterung und gehasht sie den Benutzer zu bestätigen, wurde einen Anruf von dieser Erweiterung auf die gewünschten Telefonnummer zu platzieren erlaubt.

Der Code für TransmitFile ist sehr einfach, warum es nicht ändern zu tun, was Sie brauchen?

public void TransmitFile(string filename, long offset, long length)
{
    if (filename == null)
    {
        throw new ArgumentNullException("filename");
    }
    if (offset < 0L)
    {
        throw new ArgumentException(SR.GetString("Invalid_range"), "offset");
    }
    if (length < -1L)
    {
        throw new ArgumentException(SR.GetString("Invalid_range"), "length");
    }
    filename = this.GetNormalizedFilename(filename);
    using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        long num = stream.Length;
        if (length == -1L)
        {
            length = num - offset;
        }
        if (num < offset)
        {
            throw new ArgumentException(SR.GetString("Invalid_range"), "offset");
        }
        if ((num - offset) < length)
        {
            throw new ArgumentException(SR.GetString("Invalid_range"), "length");
        }
        if (!this.UsingHttpWriter)
        {
            this.WriteStreamAsText(stream, offset, length);
            return;
        }
    }
    if (length > 0L)
    {
        bool supportsLongTransmitFile = (this._wr != null) && this._wr.SupportsLongTransmitFile;
        this._httpWriter.TransmitFile(filename, offset, length, this._context.IsClientImpersonationConfigured || HttpRuntime.IsOnUNCShareInternal, supportsLongTransmitFile);
    }
}



private void WriteStreamAsText(Stream f, long offset, long size)
{
    if (size < 0L)
    {
        size = f.Length - offset;
    }
    if (size > 0L)
    {
        if (offset > 0L)
        {
            f.Seek(offset, SeekOrigin.Begin);
        }
        byte[] buffer = new byte[(int) size];
        int count = f.Read(buffer, 0, (int) size);
        this._writer.Write(Encoding.Default.GetChars(buffer, 0, count));
    }
}


internal void TransmitFile(string filename, long offset, long size, bool isImpersonating, bool supportsLongTransmitFile)
{
    if (this._charBufferLength != this._charBufferFree)
    {
        this.FlushCharBuffer(true);
    }
    this._lastBuffer = null;
    this._buffers.Add(new HttpFileResponseElement(filename, offset, size, isImpersonating, supportsLongTransmitFile));
    if (!this._responseBufferingOn)
    {
        this._response.Flush();
    }
}

Danke,

Phil.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top