문제

웹 사이트 사용자에게 다운로드 가능한 파일을 제공하고 싶지만 사용자로부터 파일의 URL을 숨기고 싶습니다 ... httphandler가 트릭을 수행 할 수 있다고 생각하지만 외부 서버에서 파일을 검색 할 수 있습니다. 사용자에게 스트리밍 하시겠습니까?

아마도 누군가가 이것을 달성하는 방법에 대한 힌트를 줄 수 있습니까?


내가 달성하려는 것을 자세히 설명하기 위해 ... 음악 다운로드 링크가 포함 된 ASP.NET 웹 사이트를 구축하고 있습니다. 파일의 실제 URL을 보호하고 싶습니다. 또한 외부 (PHP) 서버 (훨씬 저렴한)에 저장하고 싶습니다.

따라서 제가해야 할 일은 URL에서 파일을 잡을 수있는 스트림을 설정하고 (다른 서버를 가리키는 지) 사용자가 다른 서버에서 나오는 것을 인식하지 않고 응답 객체로 스트리밍하는 것입니다.

TransmitFile 메소드가 완전히 별도의 서버에서 파일을 스트리밍 할 수 있습니까? 목적 (대역폭 저장)을 물리 치기 때문에 파일을 "내버"를 통해 스트리밍하기를 원하지 않습니다 ... 클라이언트 (브라우저)가 다른 서버에서 직접 파일을 다운로드하기를 원합니다.

파일 호스팅 서버에 핸들러가 필요합니까? 다른 쪽 끝에있는 PHP 스크립트가가는 길입니다 ...?

도움이 되었습니까?

해결책

대역폭이 외부 서버에서 나오지 않기를 원한다는 설명으로 질문을 상당히 변경합니다.

이를 달성하려면 외부 서버에 웹 사이트가 있어야합니다. 사이트를 통해 파일을 스트리밍 할 수는 없지만 대역폭에 맞지 않거나 사이트에서 제어하지만 다른 서버를 통해 스트리밍되므로 다른 사이트를 통해 완전히 처리해야합니다. 이 문제는 일반적인 URL 기반 접근 방식으로 URL을 표시하지 않는 두 번째 요구 사항이라고 사용자에게 표시합니다.

그러나 외부 사이트의 파일을 제공하는 일반적인 페이지와 원래 사이트의 페이지에서 게시물을 통해 전달되는 파일에 대한 세부 사항을 가질 수 없습니까? 특정 파일을 가리키는 URL을 제거합니다. 도메인이 표시되지만 사용자는 게시물 필드를 모르면 파일을 가져올 수 없습니다.

이것은 httphandler 일 필요는 없으며 일반 페이지 일뿐입니다.

다른 팁

Transmitfile 메소드를 보는 것이 좋습니다. http://msdn.microsoft.com/en-us/library/12s31dhy.aspx

예, 원격 스트림 (다른 서버에서 다운로드)에서 출력 스트림까지 스트리밍 할 수 있습니다. 추정하다 Serviceurl 스트리밍 할 파일의 위치입니다.

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

나는 전에 이것을 해냈다. 첫째, 분명히 파일은 웹 사이트의 사용자 프로세스가 액세스 할 수있는 외부 서버에서 공유해야합니다.

httphandler가 진행하는 한, 나는 사용자에게 다운로드하려는 파일이 포함 된 zip 파일을 제공함으로써 이것을 처리했다. 이렇게하면 내 핸들러가 .zip 파일을 호출하고 내가 만든 zip 파일을 스트리밍 할 수 있습니다.

코드는 다음과 같습니다 (상당히 청크; MVP를 사용하므로 핸들러 및 발표자로 분할) : 핸들러 :

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
}

증여자:

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

도움이 되었기를 바랍니다!!

좋아요, 일부 PHP 코드 작성/ 배포를 피하려는 퀘스트는 헛된 것 같습니다 ... 여기 파일 (PHP) 서버에서 실행할 내용은 다음과 같습니다.

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

ASP.NET 웹 서버의 링크가 해당 스크립트를 가리키면 관련 파일을 다운로드합니다 (따라서 직접 다운로드를 피하고 Google 웹 로그 분석을 통해 다운로드 추적을 허용합니다) ...

모든 Greg 감사합니다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top