2010-09-19 18 views
8

मेरे पास कोड का निम्न ब्लॉक है जो मेरे स्प्रिंग एमवीसी वेब एप्लिकेशन में उपयोग की जा रही एक तस्वीर का एक फ़ाइल अपलोड कर रहा है। मैं फाइल अपलोड को संभालने के लिए स्प्रिंग एमवीसी कॉमन्स मल्टीपार्टफाइल रीसोल्वर का उपयोग कर रहा हूं।स्प्रिंग फ़ाइल के साथ समस्या

if(model.getPhoto() != null){ 
    if(!model.getPhoto().isEmpty()){ 
     MultipartFile file = model.getPhoto(); 
     String fileName = file.getOriginalFilename(); 
     String filePath = baseDirectory + fileName; 
     FileOutputStream fos = new FileOutputStream(filePath); 
     try 
     { 
      fos.write(file.getBytes()); 
      agentProfile.setPhotoUri(fileName); 
     } 
     catch (IllegalStateException e) 
     { 
      System.out.println(e); 

     } 
     finally 
     { 
      fos.close(); 
     } 
    } 
} 

मेरी ऐप-servlet.xml फ़ाइल में मेरे पास मल्टीपार्टफाइल रिज़ॉल्वर बीन को कॉन्फ़िगर करने के लिए निम्न कोड है।

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
</bean> 

जब मैं फ़ोटो अपलोड कर रहा हूं तो मुझे कुछ यादृच्छिक समस्याएं आ रही हैं।

1) यदि मैं एक छोटी तस्वीर अपलोड करने के लिए जाता हूं, लगभग 3 केबी या तो, यह सफलतापूर्वक अपलोड हो जाएगा।

2) यदि मैं थोड़ी बड़ी तस्वीर अपलोड करने के लिए जाता हूं, तो यह निर्देशिका में फ़ाइल बना देगा, लेकिन 0 बाइट्स के आकार के साथ और निम्न त्रुटि संदेश देगा।

java.lang.IllegalStateException: File has been moved - cannot be read again 
org.springframework.web.multipart.commons.CommonsMultipartFile.getBytes(CommonsMultipartFile.java:112) 
com.mmz.admin.mvc.controller.AddAgentController.processFinish(AddAgentController.java:145) 
org.springframework.web.servlet.mvc.AbstractWizardFormController.validatePagesAndFinish(AbstractWizardFormController.java:642) 
org.springframework.web.servlet.mvc.AbstractWizardFormController.processFormSubmission(AbstractWizardFormController.java:492) 
org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:265) 
org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153) 
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) 
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874) 
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808) 
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476) 
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:637) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 

मैं इस तरह के एक CommonsMultipartFile वस्तु को संभालने के लिए के रूप में एक सादे MultipartFile वस्तु के लिए विरोध करते हैं यह स्विचिंग के रूप में एक जोड़े को अलग अलग विकल्प मल्टीपार्ट समाधानकर्ता को विन्यस्त की कोशिश की है, लेकिन कुछ भी नहीं बदला।

मैंने निम्न संपत्ति के साथ CommonsMultipartFileResolver बीन में अधिकतम अपलोड आकार को कॉन्फ़िगर करने का भी प्रयास किया है।

<property name="maxUploadSize" value="1024000000"/> 

कुछ भी नहीं बदला। मुझे यकीन नहीं है कि CommonsMultipartResolver फ़ाइल के आकार के रूप में कितना डिफ़ॉल्ट रूप से अपलोड किया जा सकता है, लेकिन यह मेरा प्रश्न नहीं है।

मुझे बताया गया है कि जिस समस्या का मैं अनुभव कर रहा हूं वह मल्टीपार्ट पार्सर/हैंडलर में वसंत का उपयोग कर रहा है। मेरे पास इसी समस्या के बारे में हालिया पोस्ट था, और क्योंकि नई जानकारी मिली, नई जानकारी के साथ दोबारा पोस्ट करना चाहता था। पुरानी पोस्ट CommonsMultipartFileResolver Problem

मुझे लगता है कि मैंने अतिरिक्त दस्तावेज खोजने के लिए इंटरनेट पर लगभग हर संसाधन की जांच की है, लेकिन समस्या को समझने में असमर्थ हूं।

कृपया मुझे यह जानने में मदद करें कि इसके साथ क्या चल रहा है, और यदि कोई बेहतर है, तो सरल समाधान उन विकल्पों का पता लगाने के लिए समाधान हो सकता है, लेकिन अगर मैं समाधान ढूंढ सकता हूं तो मैं अपनी वर्तमान विधि के साथ रहना पसंद करूंगा।

संपादित नोट- मैं अपलोड करने के लिए अलग अलग आकार तस्वीरों के साथ प्रयोग कर रहे हैं, और मुझे विश्वास है कि सीमा है कि यह मुझे अपलोड करने के लिए अनुमति दे रहा है 10KB के आसपास है। 10Kb के बाद बड़ा कुछ भी इसे तोड़ने और मुझे ऊपर की त्रुटि दे रहा है।

+0

देखें http://stackoverflow.com/questions/11792107/multipartresolver-is-not-working – lrkwz

उत्तर

11

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

<property name="maxUploadSize" value="99999999999"/> 

वहाँ भी एक संपत्ति maxInMemorySize है कि आप अधिकतम आकार से पहले फ़ाइलों को डिस्क पर लिखा जाता है की अनुमति दी निर्दिष्ट करने के लिए अनुमति देता है।यद्यपि यह अधिकतम अपलोड आकार के समान काम करता है, यदि आप कोई राशि निर्दिष्ट नहीं करते हैं, तो यह 1024 बाइट्स तक डिफ़ॉल्ट हो जाता है। अगर मैंने बड़ी फाइल अपलोड करने का प्रयास किया तो यह इसे तोड़ने की व्याख्या करेगा।

आदेश 1024 बाइट ऊपर फ़ाइलों अनुमति देने के लिए अपलोड की गई हो, आप जो कुछ भी आप निम्नलिखित की तरह की जरूरत के लिए maxInMemorySize मूल्य में वृद्धि करने की आवश्यकता है ...

यह वही है मेरी समस्या का ध्यान रखा है। मैंने सीखा है कि यह गुण 1024 के लिए डिफ़ॉल्ट है जब मैं CommonsFileUpload दस्तावेज़ीकरण के लिए दस्तावेज़ की समीक्षा कर रहा था।

आप CommonsFileUpload Documentation

पर इस दस्तावेज़ देख सकते हैं मुझे आशा है कि यह किसी को भी मदद करता है, के रूप में वहाँ CommonsMultipartFile के प्रयोग पर बहुत अच्छा प्रलेखन नहीं है।

+1

अच्छा लगता है, हालांकि मुझे यह महसूस हो रहा है कि इस डिफ़ॉल्ट सेटिंग को टूटी हुई अपलोडों का कारण नहीं होना चाहिए था। मैं स्प्रिंग लड़कों को इस मुद्दे के बारे में क्या कहना है, यह देखने के लिए एक मुद्दे की रिपोर्ट करूंगा। – BalusC

+0

मैं, मैं इस मुद्दे में और अधिक देखने जा रहा हूं। यह आश्चर्य की बात है कि अगर कुछ भी निर्दिष्ट नहीं किया गया है, लेकिन दूसरे को नहीं तो वे 1024 से डिफ़ॉल्ट होंगे। – TheJediCowboy

+0

आपके द्वारा संदर्भित लिंक के अनुसार, डिफ़ॉल्ट 10240 बाइट्स है (आपके पहले अनुभवजन्य परिणाम को समझाता है)। –

3

मुझे लगता है कि यह त्रुटि तब होती है जब फ़ाइल 1024 बाइट्स से अधिक होती है और आप फ़ाइल को दो बार पढ़ने की कोशिश करते हैं। जैसा कि CitadelCSAlum उल्लेख करता है, maxInMemorySize = maxUploadSize को सेट करने से इस समस्या को ठीक किया जाएगा, लेकिन किसी को स्मृति उपयोग को ध्यान में रखना चाहिए। यदि स्मृति एक चिंता है, तो दूसरा विकल्प मल्टीपार्ट फ़ाइल डेटा को पहले पढ़ने पर एक temp फ़ाइल में लिखना है और बाद में पढ़ने के लिए उस फ़ाइल का उपयोग करना है। यदि आप दो बार नहीं पढ़ते हैं तो आपको maxInMemorySize बढ़ाने की आवश्यकता नहीं है।

2

आपके प्रश्न में उल्लिखित अपवाद कहता है: "फ़ाइल ले जाया गया है - फिर से पढ़ा नहीं जा सकता"। ऐसा इसलिए है क्योंकि हम मल्टीपार्ट फ़ाइल से एक से अधिक बार इनपुटस्ट्रीम पढ़ने की कोशिश कर रहे हैं।

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

फ़ाइल का आकार बहुत छोटा होने पर मुझे इस समस्या का सामना नहीं करना पड़ता है। "TransferTo" विधि में "isAvailable" विधि के लिए एक आंतरिक कॉल है। स्मृति में बचाने

  1. यदि यह बहुत छोटा है, वसंत और जब हम फ़ाइल के लिए पूछना यह पुनर्प्राप्त:

    protected boolean More ...isAvailable() { 
          // If in memory, it's available. 
         if (this.fileItem.isInMemory()) { 
          return true; 
         } 
         // Check actual existence of temporary file. 
         if (this.fileItem instanceof DiskFileItem) { 
          return ((DiskFileItem) this.fileItem).getStoreLocation().exists(); 
         } 
         // Check whether current file size is different than original one. 
         return (this.fileItem.getSize() == this.size); 
        } 
    

    लिंक: http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-web/3.2.1.RELEASE/org/springframework/web/multipart/commons/CommonsMultipartFile.java#CommonsMultipartFile.isAvailable%28%29

    टिप्पणियों नीचे कोड खंड का पालन करें याद से। हम इसे कई बार पूछ सकते हैं क्योंकि फ़ाइल स्मृति में है।

  2. यदि यह काफी बड़ा है, तो वसंत इसे एक अस्थायी फ़ाइल के रूप में सहेज लेगा जिसे हम स्थान नहीं जानते हैं, लेकिन जब हम वसंत द्वारा आंतरिक रूप से हटाए जा सकते हैं तो इनपुट इनपुट को पढ़ने के बाद। फिर जब हम दूसरी बार पूछते हैं कि त्रुटि कहती है "फिर से पढ़ा नहीं जा सकता"।

तो मेरी समाधान पहले मैं "transferTo" पद्धति का उपयोग करके सर्वर शहर के दौरे में सहेजने और मान्य करने के लिए है कि स्थानीय फ़ाइल या किसी अन्य दूसरी बार जरूरत पुनर्प्राप्त करने के लिए है है।

मुझे लगता है कि "multipartResolver" बीन में "maxUploadSize" को बढ़ाने के लिए अच्छा नहीं है क्योंकि फ़ाइल बहुत बड़ी है तो यह अधिक स्मृति का उपभोग करती है।

+1

यह वास्तव में प्रश्न का उत्तर नहीं देता है। यदि आपके पास कोई अलग प्रश्न है, तो आप [प्रश्न पूछें] (http://stackoverflow.com/questions/ask) पर क्लिक करके पूछ सकते हैं। एक बार आपके पास पर्याप्त [प्रतिष्ठा] (http://stackoverflow.com/help/) हो जाने पर आप इस प्रश्न पर अधिक ध्यान आकर्षित करने के लिए [एक बक्षीस] (http://stackoverflow.com/help/privileges/set-bounties) भी जोड़ सकते हैं। क्या-प्रतिष्ठा)। – apaul

+0

मैं उस बिंदु के लिए सहमत नहीं हूं। यह अपवाद तब आता है जब "CommonsMultipartFile" वर्ग में "getBytes" विधि को कॉल किया जाता है। मेरे मामले में मैं "transferTo" विधि का उपयोग करता हूं, और दोनों स्थितियों में यह "उपलब्ध है" विधि को कॉल करेगा। यदि हम पहले से ही उस मल्टीपार्ट फ़ाइल के इनपुटस्ट्रीम का उपयोग करते हैं तो यह अपवाद होगा। तो मेरा समाधान सबसे पहले हमें उस फ़ाइल को किसी सर्वर स्थान पर सहेजने की आवश्यकता है और उस फ़ाइल को कोई सत्यापन करने के लिए प्राप्त करें। क्योंकि अगर वह सीमा समाप्त हो गई है, तो वसंत डिस्क में उस फ़ाइल को डिस्क में संग्रहीत नहीं करेगा। जब हम एक बार पढ़ते हैं तो यह डिस्क में उस अस्थायी फ़ाइल को हटा देगा। लेकिन अगर यह बहुत छोटा है तो यह स्मृति में रहेगा। – Arosha

+0

इसके बारे में खेद है, आपके उत्तर के शब्द/स्वरूपण को देखते हुए यह एक "मुझे एक ही समस्या है" टिप्पणी की तरह लग रहा था। मैंने अपना डाउनवोट वापस ले लिया। – apaul

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