httphandler 다른 서버에서 다운로드 파일을 검색하려면?
-
03-07-2019 - |
문제
웹 사이트 사용자에게 다운로드 가능한 파일을 제공하고 싶지만 사용자로부터 파일의 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 감사합니다