2012-06-18 17 views
5

खाने के लिए मैं एक आईएचटीपी हैंडलर पर एक फ़ाइल स्थानांतरित करने की कोशिश कर रहा हूं, कोड बहुत आसान है। हालांकि जब मैं एक ही स्थानांतरण शुरू करता हूं तो यह लगभग 20% CPU का उपयोग करता है। अगर मैं इसे 20 एक साथ स्थानांतरित करने के लिए स्केल करना था तो सीपीयू बहुत अधिक है। क्या सीपीयू को कम रखने के लिए मैं ऐसा कर सकता हूं? क्लाइंट कोड सिर्फ एक समय में 64KB फ़ाइल के हिस्सों पर भेजता है।फ़ाइल स्थानांतरण बहुत सी 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(); 
} 

यहाँ मेरे मुवक्किल कोड है:

//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

आप अपने सीपीयू उपयोग आंकड़ों को किस आधार पर रखते हैं? – CodingGorilla

+0

स्थानांतरण शुरू करना और परफमन देखना। मैं इसका उपयोग कर अकेला हूं। –

+0

क्या यह विकास मशीन या वास्तविक सर्वर पर है? – CodingGorilla

उत्तर

1

मैं इस सिद्धांत का परीक्षण नहीं किया है, लेकिन FromBase64String के साथ काम करने का कारण हो सकता है। मुझे this case मिला जहां कोई इस विधि का उपयोग कर स्मृति से बाहर चला रहा था।

इसके बजाय आप FromBase64Transform को आजमा सकते हैं, जिसे डेटा की स्ट्रीम को संभालने के लिए डिज़ाइन किया गया है।


या आप किसी भी कारण से बेस 64 उपयोग करने के लिए, this solution from Scott Hanselman की जाँच की ज़रूरत नहीं है, तो।

+0

दिलचस्प है, मैं इसे एक शॉट दूंगा। प्रश्न हालांकि, मैं बेस 64 विशेषज्ञ या कुछ भी नहीं हूं, लेकिन चूंकि मेरा परिवहन एसएसएल है, क्या मुझे बेस 64 में बाइट सरणी को एन्कोड करने की भी आवश्यकता है? –

+0

मुझे नहीं पता था कि आप वास्तव में बेस 64 का उपयोग क्यों कर रहे थे। लेकिन अपने प्रश्न का उत्तर देने के लिए, आपको SSL पर स्थानांतरित फ़ाइल के लिए बेस 64 डिकोडिंग करने की आवश्यकता नहीं होगी। समाधान के लिए इसे देखें (मान लें कि आप मल्टीपार्ट/फॉर्म-डेटा का उपयोग कर रहे हैं) ... http://www.hanselman.com/blog/ABackToBasicsCaseStudyImplementingHTTPFileUploadWithASPNETMVCIncludingTestsAndMocks.aspx –

+0

मैंने बाइट सरणी को स्ट्रिंग में कनवर्ट करने की इस विधि का उपयोग करने का प्रयास किया (http://stackoverflow.com/questions/472906/net-string-to-byte-array-c-sharp) और इसे http हैंडलर पर बाइट सरणी में डीकोड करना और यह अभी भी 15% cpu (और फ़ाइल को दूषित कर दिया गया है)) ...वास्तव में सुनिश्चित नहीं है कि मैं पैरामीटर में बाइट सरणी कैसे और परिवहन कर सकता हूं। –

संबंधित मुद्दे