2010-02-26 3 views
0

그래서 C# (Securing Large Downloads Using C# and IIS 7)을 사용하여 다운로드 보안에 대해 잠시 물어 보았습니다. 파일을 메모리로 읽은 다음 사용자에게 쓰는 방법에 대한 훌륭한 조언을 받았습니다. 유일한 문제는 이제 기본 로깅을 구현하려고하는데, 저는 벽돌 벽을 치고 있습니다. 여기에 파일을 스트리밍 할 수있는 코드입니다 :.NET - 클라이언트 연결 시간으로 파일 스트리밍?

public void StreamFile(string file_path) 
{ 
    DateTime start; 
    TimeSpan ts; 
    FileStream fstream; 
    string filename = Path.GetFileName(file_path); 
    byte[] buffer = new byte[STREAM_BUFFER_SIZE]; 
    int count = 1, total = 0, seconds; 

    // Open the file to read 
    fstream = new FileStream("D:\\" + file_path, FileMode.Open, FileAccess.Read); 

    // Set up the response headers 
    Response.AddHeader("Content-Length", fstream.Length.ToString()); 
    Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); 
    Response.ContentType = "application/octet-stream"; 

    // If the user agent is Internet Explorer, we add one last header 
    if (Request.UserAgent.Contains("MSIE")) 
     Response.AddHeader("Content-Transfer-Encoding", "binary"); 

    // Start counting the time 
    start = DateTime.Now; 

    // Now, until the client disconnects, we stream the file 
    while (Response.IsClientConnected) 
    { 
     // Read the file into the buffer 
     count = fstream.Read(buffer, 0, buffer.Length); 

     // If the buffer is empty, break out of the loop. We're done! 
     if (count == 0) 
      break; 

     // Write to the output stream and push it to the user 
     Response.OutputStream.Write(buffer, 0, count); 
     Response.Flush(); 

     // Increment the total as well, this way we can know how much we've streamed 
     total += count; 
    } 
    // The transfer is done! Close the connection. 
    Response.Close(); 

    // Count the number of seconds 
    ts = DateTime.Now - start; 
    seconds = ts.Seconds + (60 * ts.Minutes) + (60 * 60 * ts.Hours); // Also, is there a better way to do this? This is laaaaaame! 

    // Finally, log the transfer 
    Logging.AddLog(Request["user"], file_path, total, count == 0, seconds); 
} 

이 좋아, 그래서 문제는,이 초에 완료 파일이 들어, 메모리에 파일을 읽을 수 없습니다했다 말할 생성되는 로그 항목입니다 사용자가 그것을 다운로드하십시오. 나는 Response.ClientConnected가 그 일을 처리한다고 가정하지만 분명히 그렇지는 않습니다. 따라서 로그에 의해보고 된 파일을 다운로드하는 시간은 0-1 초이며, 다운로드 부분을 끝내더라도 로그는 모든 것을 제공했다고 말합니다.

누구나 이전에 이와 같은 작업을 수행했거나 이전 아이디어를 통해 어떻게 실제 번호를 얻을 수 있습니까? 이 정보를 얻는 것이 불행히도 큰 우선 순위입니다. 아니면 그냥 두지 말고 두 가지 값을 모두 로깅에서 제거하십시오.

답변

1

죄송합니다. 원하시는 것을 할 수 없을 수도 있습니다. Write() (NetworkStream)에 전화하면 즉시 데이터가 Windows 소켓에 전달되고 데이터는 네트워크 카드의 버퍼에 기록됩니다. 따라서 .Net은 버퍼링을 수행하지 않고 Write는 즉시 반환합니다. NetworkStream은 .Net에 의해 버퍼링되지 않으므로 Flush()을 호출해도 아무런 효과가 없습니다. 따라서 .Net에서 데이터가 네트워크 카드의 버퍼를 벗어날 때까지 기다릴 수 없습니다.

데이터가 NIC의 버퍼를 벗어날 때까지 정확히 어떤 방법으로도 기다리지 만 클라이언트가 데이터를 수신했다는 보장이 없습니다.

+0

흠, 다른 사람이이 작업을 수행 할 수있는 방법을 생각해 낼 수 없다면이 내용을 인정할 것입니다. 어쩌면 내가 원하는 것을 얻기 위해 IIS 로그를 파싱해야 할 것입니다. –

0

해결책은 클라이언트 응용 프로그램에 전체 파일이 있으면 "수신 된"확인 패킷을 다시 보내도록하는 것입니다. 일단 그 사실을 알게되면 실제로 모든 것을 받았음을 알게되고 타이머를 멈출 수 있습니다.

+0

표준 웹 브라우저 이외의 '클라이언트 응용 프로그램'이 없으면 정보가 더 정확할 클라이언트 측에서 로깅이 발생합니다. –