Domanda

Vorrei fornire file scaricabili agli utenti del sito Web, ma voglio nascondere l'URL dei file all'utente ... Sto pensando che un HTTPHandler potrebbe fare il trucco, ma è possibile recuperare un file da un server esterno e trasmetterlo in streaming all'utente?

Forse qualcuno può darmi un suggerimento su come ottenere questo risultato o indicarmi una risorsa su cui è stato fatto prima?


Solo per approfondire ciò che sto cercando di ottenere ... Sto costruendo un sito Web ASP.NET, che contiene un collegamento per il download di musica. Voglio proteggere gli URL reali del file e voglio anche salvarli su un server esterno (PHP) (MOLTO MOLTO più economico) ...

Quindi quello che devo fare è impostare uno stream che può prendere il file da un URL (punta a un altro server) e trasmetterlo all'oggetto Response senza che l'utente si accorga che proviene da un altro server.

Il metodo TransmitFile consentirà lo streaming di un file da un server completamente separato? Non voglio che il file sia trasmesso in streaming da " a " il mio server, poiché ciò vanifica lo scopo (risparmio della larghezza di banda) ... Voglio che il client (browser) scarichi il file direttamente dall'altro server.

Forse ho bisogno di un gestore sul server di file hosting? Forse uno script PHP all'altra estremità è la strada da percorrere ...?

È stato utile?

Soluzione

Con il tuo chiarimento sul volere che la larghezza di banda provenga dal server esterno e non dal tuo, cambia un po 'la domanda.

Per fare ciò, il server esterno dovrebbe avere un sito Web su di esso che potresti inviare all'utente. Non puoi eseguire lo streaming del file attraverso il tuo sito ma non essere colpito dalla larghezza di banda o controllarlo dal tuo sito ma trasmesso in streaming sull'altro server, quindi deve essere gestito completamente attraverso l'altro sito. Il problema è che un normale approccio basato sull'URL mostrerebbe all'utente l'URL, che hai detto è il secondo requisito che non mostra l'URL.

Ma non potresti semplicemente avere una pagina generica che serve i file sul sito esterno e le specifiche su quale file eseguire lo streaming passerebbero attraverso un post dalla pagina sul sito originale? Ciò eliminerebbe l'URL che punta a un file specifico. Mostrerebbe il dominio, ma gli utenti non sarebbero in grado di estrarre i file senza conoscere i campi dei post.

Questo non dovrebbe essere un HTTPHandler, solo una pagina normale.

Altri suggerimenti

Ti consiglio di guardare il metodo TransmitFile: http: // msdn. microsoft.com/en-us/library/12s31dhy.aspx

Sì, è possibile eseguire lo streaming da un flusso remoto (scaricare da un altro server) al flusso di output. Supponiamo che serviceUrl sia la posizione del file per lo streaming:

HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
            webrequest.AllowAutoRedirect = false;
            webrequest.Timeout = 30 * 1000;
            webrequest.ReadWriteTimeout = 30 * 1000;
            webrequest.KeepAlive = false;

            Stream remoteStream = null;
            byte[] buffer = new byte[4 * 1024];
            int bytesRead;

            try {
                WebResponse responce = webrequest.GetResponse();
                remoteStream = responce.GetResponseStream();
                bytesRead = remoteStream.Read(buffer, 0, buffer.Length);

                Server.ScriptTimeout = 30 * 60;
                Response.Buffer = false;
                Response.BufferOutput = false;
                Response.Clear();
                Response.ContentType = "application/octet-stream";
                Response.AppendHeader("Content-Disposition", "attachment; filename=" + Uid + ".EML");
                if (responce.ContentLength != -1)
                    Response.AppendHeader("Content-Length", responce.ContentLength.ToString());

                while (bytesRead > 0 && Response.IsClientConnected) {
                    Response.OutputStream.Write(buffer, 0, bytesRead);
                    bytesRead = remoteStream.Read(buffer, 0, buffer.Length);
                }

            } catch (Exception E) {
                Logger.LogErrorFormat(LogModules.DomainUsers, "Error transfering message from remote host: {0}", E.Message);
                Response.End();
                return;
            } finally {
                if (remoteStream != null) remoteStream.Close();
            }

            Response.End();

L'ho già fatto prima. Innanzitutto, e ovviamente, i file devono essere in una condivisione sul server esterno a cui il processo utente del sito Web ha accesso.

Per quanto riguarda HTTPHandler, ho gestito questo dando agli utenti i file zip contenenti i file che volevano scaricare; in questo modo il mio gestore potrebbe intercettare qualsiasi chiamata per i file .zip e trasmetterli in streaming il file zip che creo.

Ecco il codice (un bel pezzo; io uso MVP, quindi è diviso in Handler e Presenter): Handler:

public class ZipDownloadModule: IHttpHandler, ICompressFilesView, IErrorView 
{
    CompressFilesPresenter _presenter;

    public ZipDownloadModule()
    {
        _presenter = new CompressFilesPresenter(this, this);
    }
    #region IHttpHandler Members

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        OnDownloadFiles();
    }

    private void OnDownloadFiles()
    {
        if(Compress != null)
            Compress(this, EventArgs.Empty);
    }

    #endregion

    #region IFileListDownloadView Members

    public IEnumerable<string> FileNames
    {
        get 
        {
            string files = HttpContext.Current.Request["files"] ?? string.Empty;

            return files.Split(new Char[] { ',' });
        }
    }

    public System.IO.Stream Stream
    {
        get
        {
            HttpContext.Current.Response.ContentType = "application/x-zip-compressed";
            HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=ads.zip");
            return HttpContext.Current.Response.OutputStream;
        }
    }

    public event EventHandler Compress;

    #endregion

    #region IErrorView Members

    public string errorMessage
    {
        set {  }
    }

    #endregion
}

Presenter:

public class CompressFilesPresenter: PresenterBase<ICompressFilesView>
{
    IErrorView _errorView;

    public CompressFilesPresenter(ICompressFilesView view, IErrorView errorView)
        : base(view)
    {
        _errorView = errorView;
        this.View.Compress += new EventHandler(View_Compress);
    }

    void View_Compress(object sender, EventArgs e)
    {
        CreateZipFile();
    }

    private void CreateZipFile()
    {
        MemoryStream stream = new MemoryStream();

        try
        {
            CreateZip(stream, this.View.FileNames);

            WriteZip(stream);
        }
        catch(Exception ex)
        {
            HandleException(ex);
        }
    }

    private void WriteZip(MemoryStream stream)
    {
        byte[] data = stream.ToArray();

        this.View.Stream.Write(data, 0, data.Length);
    }

    private void CreateZip(MemoryStream stream, IEnumerable<string> filePaths)
    {
        using(ZipOutputStream s = new ZipOutputStream(stream)) // this.View.Stream))
        {
            s.SetLevel(9); // 0 = store only to 9 = best compression

            foreach(string fullPath in filePaths)
                AddFileToZip(fullPath, s);

            s.Finish();
        }
    }

    private static void AddFileToZip(string fullPath, ZipOutputStream s)
    {
        byte[] buffer = new byte[4096];

        ZipEntry entry;

        // Using GetFileName makes the result compatible with XP
        entry = new ZipEntry(Path.GetFileName(fullPath));

        entry.DateTime = DateTime.Now;
        s.PutNextEntry(entry);

        using(FileStream fs = File.OpenRead(fullPath))
        {
            int sourceBytes;
            do
            {
                sourceBytes = fs.Read(buffer, 0, buffer.Length);
                s.Write(buffer, 0, sourceBytes);
            } while(sourceBytes > 0);
        }
    }

    private void HandleException(Exception ex)
    {
        switch(ex.GetType().ToString())
        {
            case "DirectoryNotFoundException":
                _errorView.errorMessage = "The expected directory does not exist.";
                break;
            case "FileNotFoundException":
                _errorView.errorMessage = "The expected file does not exist.";
                break;
            default:
                _errorView.errorMessage = "There has been an error. If this continues please contact AMG IT Support.";
                break;
        }
    }

    private void ClearError()
    {
        _errorView.errorMessage = "";
    }
}

Spero che questo aiuti !!

Okay, sembra che la mia ricerca per evitare di scrivere / distribuire un codice php sia vana ... ecco cosa ho intenzione di eseguire sul server file (php):

http://www.zubrag.com/scripts/download.php

Quindi i collegamenti dal mio server web asp.net indicheranno quello script, che quindi scaricherà il file pertinente (evitando quindi i download diretti e consentendo il tracciamento dei download tramite Google Analytics) ... penso che lo farà il trucco

Grazie a tutti Greg

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top