HTTPHandler pour récupérer le fichier de téléchargement à partir d'un autre serveur?

StackOverflow https://stackoverflow.com/questions/160651

  •  03-07-2019
  •  | 
  •  

Question

Je souhaite fournir des fichiers téléchargeables aux utilisateurs du site Web, mais je souhaite masquer l'URL des fichiers à l'utilisateur ... Je pense qu'un gestionnaire HTTPHandler pourrait faire l'affaire, mais est-il possible de récupérer un fichier à partir d'un fichier. serveur externe et le diffuser à l'utilisateur?

Peut-être que quelqu'un pourrait me donner un indice sur la façon de procéder, ou me diriger vers une ressource où cela avait été fait auparavant?

Pour en savoir plus sur ce que je tente d’atteindre ... Je construis un site Web ASP.NET, qui contient un lien de téléchargement de musique. Je souhaite protéger les URL réelles du fichier et les stocker sur un serveur externe (PHP) (BEAUCOUP BEAUCOUP moins cher) ...

Je dois donc configurer un flux capable de récupérer le fichier depuis une URL (pointant vers un autre serveur) et de le diffuser vers l'objet Response sans que l'utilisateur ne réalise qu'il provient d'un autre serveur.

La méthode TransmitFile permettra-t-elle la diffusion en continu d'un fichier à partir d'un serveur complètement séparé? Je ne souhaite pas que le fichier soit transféré " par le biais de " mon serveur, car cela va à l'encontre de l'objectif (économie de bande passante) ... Je souhaite que le client (navigateur) télécharge le fichier directement depuis l'autre serveur.

Ai-je peut-être besoin d'un gestionnaire sur le serveur d'hébergement de fichiers? Peut-être qu’un script PHP à l’autre bout serait la solution ...?

Était-ce utile?

La solution

Si vous souhaitez préciser que la bande passante doit provenir du serveur externe et non du vôtre, la question change un peu.

Pour ce faire, le serveur externe devrait avoir un site Web sur lequel vous pourriez envoyer l'utilisateur. Vous ne pouvez pas diffuser le fichier via votre site sans vous faire toucher par la bande passante, ni le contrôler depuis votre site, mais le diffuser via l'autre serveur. Il doit donc être entièrement géré via l'autre site. Le problème avec cela est une approche basée sur une URL normale qui montrerait à l’URL l’URL, ce qui, selon vous, est la deuxième condition requise pour ne pas afficher l’URL.

Mais, ne pourriez-vous pas simplement avoir une page générique qui sert les fichiers sur le site externe et les détails sur le fichier à diffuser qui serait transmis via une publication de la page du site d'origine? Cela supprimerait l'URL pointant sur un fichier spécifique. Cela montrerait le domaine, mais les utilisateurs ne pourraient pas extraire des fichiers sans connaître les champs de publication.

Cela n'aurait pas besoin d'être un HTTPHandler, mais une page normale.

Autres conseils

Je vous recommande de consulter la méthode TransmitFile: http: // msdn. microsoft.com/en-us/library/12s31dhy.aspx

Oui, vous pouvez diffuser depuis un flux distant (téléchargement depuis un autre serveur) vers le flux de sortie. Supposons que serviceUrl correspond à l'emplacement du fichier à diffuser:

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();

Je l'ai déjà fait auparavant. Tout d’abord, il est évident que les fichiers doivent se trouver sur un partage sur le serveur externe auquel le processus utilisateur du site Web a accès.

Pour ce qui est de HTTPHandler, j’ai traité cela en donnant aux utilisateurs des fichiers zip contenant les fichiers qu’ils veulent télécharger; Ainsi, mon gestionnaire pourra intercepter tout appel de fichiers .zip et les diffuser en streaming avec le fichier zip que je crée.

Voici le code (un morceau assez important; j'utilise MVP, il est donc divisé en gestionnaire et présentateur): Gestionnaire:

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
}

Présentateur:

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 = "";
    }
}

J'espère que ça aide !!

D'accord, ma quête pour éviter d'écrire / déployer du code php est en vain ... voici ce que je vais exécuter sur le serveur de fichiers (php):

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

Ensuite, les liens de mon serveur Web asp.net pointeront vers ce script, qui téléchargera ensuite le fichier approprié (évitant ainsi les téléchargements directs et permettant le suivi des téléchargements via Google Analytics) ... Je pense que cela suffira. le truc

Merci à tous Greg

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top