2012-06-18 33 views
5

Tôi đang cố truyền tệp qua IHttpHandler, mã này khá đơn giản. Tuy nhiên khi tôi bắt đầu một lần chuyển, nó sử dụng khoảng 20% ​​CPU. Nếu tôi đã được quy mô này đến 20 đồng thời chuyển CPU là rất cao. Có cách nào tốt hơn tôi có thể làm điều này để giữ cho CPU thấp hơn? mã máy khách chỉ gửi qua các phần của tệp 64KB tại một thời điểm.Truyền tệp đang ăn nhiều CPU

public void ProcessRequest(HttpContext context) 
{ 
     if (context.Request.Params["secretKey"] == null) 
     { 

     } 
     else 
     { 
      accessCode = context.Request.Params["secretKey"].ToString(); 
     } 

     if (accessCode == "test") 
     { 
      string fileName = context.Request.Params["fileName"].ToString(); 
      byte[] buffer = Convert.FromBase64String(context.Request.Form["data"]); 
      string fileGuid = context.Request.Params["smGuid"].ToString(); 
      string user = context.Request.Params["user"].ToString(); 

      SaveFile(fileName, buffer, user); 
     } 
} 

public void SaveFile(string fileName, byte[] buffer, string user) 
{ 
     string DirPath = @"E:\Filestorage\" + user + @"\"; 

     if (!Directory.Exists(DirPath)) 
     { 
      Directory.CreateDirectory(DirPath); 
     } 

     string FilePath = @"E:\Filestorage\" + user + @"\" + fileName; 
     FileStream writer = new FileStream(FilePath, File.Exists(FilePath) ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.ReadWrite); 
     writer.Write(buffer, 0, buffer.Length); 
     writer.Close(); 
} 

Đây là mã khách hàng của tôi:

//Set filename from object 
       string FileName; 
       FileName = System.IO.Path.GetFileName(pubAttFullPath.ToString()); 

       //Open file 
       string file = System.IO.Path.GetFileName(pubAttFullPath.ToString()); 
       FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); 
       //Chunk size that will be sent to Server 
       int chunkSize = 65536; 
       // Unique file name 
       string fileName = smGuid.ToString() + "_" + FileName; 
       int totalChunks = (int)Math.Ceiling((double)fileStream.Length/chunkSize); 
       // Loop through the whole stream and send it chunk by chunk; 
       for (int i = 0; i < totalChunks; i++) 
       { 
        bool doRecieve = true; 
        int cpt = 0; 
        do 
        { 
         int startIndex = i * chunkSize; 
         int endIndex = (int)(startIndex + chunkSize > fileStream.Length ? fileStream.Length : startIndex + chunkSize); 
         int length = endIndex - startIndex; 

         byte[] bytes = new byte[length]; 
         fileStream.Read(bytes, 0, bytes.Length); 


         //Request url, Method=post Length and data. 
         string requestURL = "http://localhost:16935/Transfer.doit"; 
         HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestURL); 
         // Wait 5 min for answer before close connection. 
         request.Timeout = 300000; 
         request.Method = "POST"; 
         request.ContentType = "application/x-www-form-urlencoded"; 

         // Chunk(buffer) is converted to Base64 string that will be convert to Bytes on the handler. 
         string requestParameters = @"fileName=" + fileName + @"&secretKey=test" + @"&currentChunk=" + i + @"&totalChunks=" + totalChunks + @"&smGuid=" + smGuid 
         + "&user=" + userSID.ToString() + 
         "&data=" + HttpUtility.UrlEncode(Convert.ToBase64String(bytes)); 

         // finally whole request will be converted to bytes that will be transferred to HttpHandler 
         byte[] byteData = Encoding.UTF8.GetBytes(requestParameters); 

         request.ContentLength = byteData.Length; 
         try 
         { 
          Stream writer = request.GetRequestStream(); 
          writer.Write(byteData, 0, byteData.Length); 
          writer.Close(); 
          // here we will receive the response from HttpHandler 
          StreamReader stIn = new StreamReader(request.GetResponse().GetResponseStream()); 
          string strResponse = stIn.ReadToEnd(); 
          stIn.Close(); 
          doRecieve = true; 
         } 
         catch (WebException webException) 
         { 
          if (webException.Status == WebExceptionStatus.ConnectFailure || 
           webException.Status == WebExceptionStatus.ConnectionClosed || 
           webException.Status == WebExceptionStatus.ReceiveFailure || 
           webException.Status == WebExceptionStatus.SendFailure || 
           webException.Status == WebExceptionStatus.Timeout) 
          { 
           Thread.Sleep(5000); 
           doRecieve = false; 
           cpt++; 
          } 
          else { 
           // if the exception is not those ones then get out 
           doRecieve = true; 
          } 
         } 
         catch (Exception e) 
         { 
          doRecieve = true; 
         } 
        } 
        // will try to send 3 times the current chunk before quitting 
        // can't try it so try it and give me the feedback 
        while(doRecieve == false && cpt < 3); 
       } 
+0

Bạn đang dựa vào thống kê sử dụng CPU của mình? – CodingGorilla

+0

Bắt đầu chuyển và xem perfmon. Tôi là người duy nhất sử dụng nó. –

+0

Đây có phải là máy phát triển hoặc máy chủ thực không? – CodingGorilla

Trả lời

1

tôi đã không kiểm tra giả thuyết này, nhưng làm việc với FromBase64String có thể là nguyên nhân. Tôi đã tìm thấy this case nơi một người nào đó đã hết bộ nhớ bằng phương pháp này.

Thay vào đó, bạn có thể thử FromBase64Transform, được thiết kế để xử lý luồng dữ liệu.


Hoặc nếu bạn không cần sử dụng base64 vì bất kỳ lý do gì, hãy xem this solution from Scott Hanselman.

+0

Thats thú vị, tôi sẽ cho rằng một shot. Câu hỏi mặc dù, tôi không có chuyên gia base64 hoặc bất cứ điều gì, nhưng kể từ khi giao thông của tôi là SSL, tôi thậm chí cần phải mã hóa mảng byte trong base64? –

+0

Tôi không biết tại sao bạn lại sử dụng base64. Nhưng để trả lời câu hỏi của bạn, bạn sẽ không cần phải giải mã base64 cho một tệp được truyền qua SSL. Kiểm tra điều này cho một giải pháp (giả sử bạn đang sử dụng multipart/form-data) ... http://www.hanselman.com/blog/ABackToBasicsCaseStudyImplementingHTTPFileUploadWithASPNETMVCIncludingTestsAndMocks.aspx –

+0

Tôi đã thử sử dụng phương thức chuyển đổi mảng byte thành chuỗi (http://stackoverflow.com/questions/472906/net-string-to-byte-array-c-sharp) và giải mã nó thành một mảng byte trên trình xử lý http và nó vẫn sử dụng CPU 15% (và làm hỏng tệp) ...không thực sự chắc chắn làm thế nào khác tôi có thể vận chuyển mảng byte trong các tham số. –