2009-06-25 16 views
55

पर बड़ी फ़ाइल अपलोड स्ट्रीमिंग मैं जिस एप्लिकेशन पर काम कर रहा हूं, उसके लिए मुझे उपयोगकर्ता को बहुत बड़ी फाइलें अपलोड करने की आवश्यकता है - यानी, संभावित रूप से कई गीगाबाइट्स - हमारी वेबसाइट के माध्यम से। दुर्भाग्यवश, एएसपी.नेट एमवीसी पूरे सेवा को सेवा शुरू करने से पहले रैम में लोड करना प्रतीत होता है - इस तरह के एप्लिकेशन के लिए बिल्कुल आदर्श नहीं है। विशेष रूप से, जैसे कि निम्न कोड के माध्यम से इस मुद्दे को दरकिनार करने की कोशिश कर रहा:एएसपी.नेट एमवीसी

if (request.Method == "POST") 
{ 
    request.ContentLength = clientRequest.InputStream.Length; 
    var rgbBody = new byte[32768]; 

    using (var requestStream = request.GetRequestStream()) 
    { 
     int cbRead; 
     while ((cbRead = clientRequest.InputStream.Read(rgbBody, 0, rgbBody.Length)) > 0) 
     { 
      fileStream.Write(rgbBody, 0, cbRead); 
     } 
    } 
} 

बफर-अनुरोध-में-रैम मानसिकता नाकाम करने के लिए विफल रहता है। क्या इस व्यवहार के आसपास काम करने का कोई आसान तरीका है?

+1

आपका कोड आपके आवेदन में कहां रहता है? नियंत्रक? हैंडलर? मॉड्यूल? –

+0

मुझे पता है कि यह प्रश्न पुराना है, लेकिन यह वास्तव में एक अच्छा सवाल है कि मैं जिस परियोजना पर काम कर रहा हूं उसके संदर्भ के रूप में उपयोग कर रहा हूं। त्वरित प्रश्न - आपके चरबी cbRead में इंगित करने के लिए "सीबी" क्या है? – KSwift87

+0

@ KSwift87 'cb'" बाइट्स की गिनती "के लिए खड़ा है, जो फॉग क्रीक में मानक ऐप्स हंगेरियन नोटेशन है। –

उत्तर

23

ऐसा लगता है कि मेरी प्रारंभिक कोड मूल रूप से सही था; केवल परिवर्तन की आवश्यकता

request.ContentLength = clientRequest.ContentLength; 

सामग्री की लंबाई निर्धारित करने के लिए पूरे अनुरोध में पूर्व धाराओं को

request.ContentLength = clientRequest.InputStream.Length; 

बदलने के लिए था, उत्तरार्द्ध केवल Content-Length शीर्षलेख की जांच करता है, जिसके लिए केवल हेडर को पूर्ण रूप से भेजा गया है। यह आईआईएस को लगभग तुरंत अनुरोध स्ट्रीमिंग शुरू करने की अनुमति देता है, जो मूल समस्या को पूरी तरह खत्म कर देता है।

+1

इसलिए, मूल रूप से बस इनपुटस्ट्रीम प्रॉपर्टी को स्पर्श करना आपके डिस्क बफरिंग को हरा देता है। क्या डिस्क-बफर फ़ाइल में स्ट्रीम हैंडल प्राप्त करना संभव है? –

+2

ऐसा नहीं है कि मैं निर्धारित करने में सक्षम हूं, लेकिन एक बार मुझे कुछ काम करने के बाद मैंने गंभीरता से इसकी जांच बंद कर दी। –

14

निश्चित रूप से, आप यह कर सकते हैं। RESTful file uploads with HttpWebRequest and IHttpHandler देखें। मैं कुछ वर्षों से इस विधि का उपयोग कर रहा हूं और ऐसी साइट है जिसे कम से कम कई गीगाबाइट की फाइलों के साथ परीक्षण किया गया है। अनिवार्य रूप से, आप अपना खुद का IHttpHandler बनाना चाहते हैं, जो इसे लगता है उससे आसान है।

संक्षेप में, आप एक कक्षा बनाते हैं जो IHttpHandler इंटरफ़ेस लागू करता है, जिसका अर्थ है कि आपको IsReusable संपत्ति और ProcessRequest विधि का समर्थन करना है। इसके शीर्ष पर, आपके web.config में मामूली परिवर्तन होता है, और यह एक आकर्षण की तरह काम करता है। इस चरण में अनुरोध के जीवन चक्र में, अपलोड की जाने वाली पूरी फ़ाइल को स्मृति में लोड नहीं किया जाता है, इसलिए यह स्मृति समस्याओं से बाहर कदम उठाता है।

ध्यान दें कि web.config में,

<httpHandlers> 
<add verb="*" path="DocumentUploadService.upl" validate="false" type="TestUploadService.FileUploadHandler, TestUploadService"/> 
</httpHandlers> 

फ़ाइल संदर्भित, DocumentUploadService.upl, वास्तव में मौजूद नहीं है। यह एक वैकल्पिक विस्तार देने के लिए है ताकि अनुरोध मानक हैंडलर द्वारा अवरुद्ध नहीं किया जा सके। आप अपने फ़ाइल अपलोड फॉर्म को उस पथ पर इंगित करते हैं, लेकिन फिर आपकी FileUploadHandler क्लास में प्रवेश करता है और वास्तव में फ़ाइल प्राप्त करता है।

अपडेट: असल में, मैं जिस कोड का उपयोग करता हूं वह उस लेख से अलग है, और मुझे लगता है कि यह काम करने के कारण मैं ठोकर खा रहा हूं। मैं HttpPostedFile वर्ग का उपयोग करता हूं, जिसमें "फ़ाइलें एमआईएमई मल्टीपार्ट/फॉर्म-डेटा प्रारूप में अपलोड की जाती हैं। डिफ़ॉल्ट रूप से, 256 केबी से बड़े फॉर्म फ़ील्ड और अपलोड की गई फ़ाइलों सहित सभी अनुरोध सर्वर मेमोरी में रखे जाने के बजाय डिस्क पर buffered हैं । "

if (context.Request.Files.Count > 0) 
{ 
    string tempFile = context.Request.PhysicalApplicationPath; 
    for(int i = 0; i < context.Request.Files.Count; i++) 
    { 
     HttpPostedFile uploadFile = context.Request.Files[i]; 
     if (uploadFile.ContentLength > 0) 
     { 
      uploadFile.SaveAs(string.Format("{0}{1}{2}", 
       tempFile,"Upload\\", uploadFile.FileName)); 
     } 
    } 
} 
+0

आपका कोड मेरे जैसा लगभग समान दिखता है; केवल अंतर यह है कि मैं इसे एएसपी.नेट एमवीसी में चला रहा हूं, और आप इसे सीधे एक नए IHttpHandler में चला रहे हैं। क्या आपको पता है कि एक अंतर क्यों है? क्या मेरे कोड में कुछ ऐसा है जो धारा को खींचने के लिए मजबूर कर रहा है? –

+0

मेरा अपडेट देखें, – RedFilter

+0

से ऊपर आप अपलोड प्रगति कैसे प्रदर्शित कर रहे हैं? –

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