2011-09-21 13 views
8

मेरे पास Spray का उपयोग करके एक आवेदन लिखा गया है, और मेरे पास एक पृष्ठ है जिसमें <input type="file" name="foo"> फ़ॉर्म तत्व है जो /fileUpload पर पोस्ट किया जाता है।मैं स्प्रे/स्कैला/जावा में किसी HTML फॉर्म के माध्यम से अपलोड की गई फ़ाइल को कैसे संसाधित कर सकता हूं?

मैं एक स्प्रे मार्ग इस कोड का उपयोग पथ /fileUpload को सुनने के लिए की स्थापना की है:

path("fileUpload") { 
    get { ctx => { 
    val request: HttpRequest = ctx.request 
    //Process the file, somehow with request? 
    ctx.complete("File Uploaded") 
    }} 
} 

मैं समझ नहीं कैसे पोस्ट शरीर मिलता है और फाइल पर एक संभाल पाने के लिए, और मैं ऑनलाइन कोई उदाहरण नहीं मिल रहा है।

फ़ाइल प्राप्त करना और स्प्रे या यहां तक ​​कि सरल स्कैला या जावा के माध्यम से इसे संसाधित करना संभव है, लेकिन मुझे नहीं पता कि यह कैसे करना है।

क्या कोई मदद कर सकता है?
धन्यवाद!

+3

मैं भी हैरान था क्यों में इस के लिए एक उल्लेख नहीं है मैनुअल, कोई नमूने, और इतने पर .. तो हम में से कम से कम दो हैं। वास्तव में स्प्रे के लिए कुछ सहायक होने की उम्मीद होगी। – akauppi

उत्तर

9

स्प्रे के साथ यह संभव है, हालांकि स्ट्रीमिंग ठीक से काम करता है तो मैंने जांच नहीं की है। मैं थोड़ा fiddled और इस काम की है:

post { 
    content(as[MultipartFormData]) { 
     def extractOriginalText(formData: MultipartFormData): String = { 
     formData.parts.mapValues { (bodyPart) => 
      bodyPart.content.map{ 
      (content) => new String(content.buffer) 
      } 
     }.values.flatten.foldLeft("")(_ + _) 
     } 
     formData => 
     _.complete(
      extractOriginalText(formData) 
     ); 
    } 

आप एक सेवा यह में इस कोड है कि करने के लिए एक सादा पाठ फ़ाइल अपलोड करते हैं, यह वापस ऊपर मूल पाठ खांसी। मुझे यह एक AJAX अपलोड के साथ मिलकर मिल गया है; इसे पुराने फैशन फ़ाइल अपलोड फॉर्म के साथ भी काम करना चाहिए।

ऐसा लगता है कि ऐसा करने का एक आसान तरीका होना चाहिए, विशेष रूप से सामग्री की गहरी घोंसले बल्कि बदसूरत है। अगर आपको सरलीकरण मिल जाए तो मुझे बताएं।

अद्यतन (THX akauppi):

entity(as[MultipartFormData]) { formData => 
    complete(formData.fields.map { _.entity.asString }.flatten.foldLeft("")(_ + _)) 
} 
+0

इसके अलावा, मुझे यह मेलिंग सूची https://groups.google.com/forum/#!topic/spray-user/_ZcXPqYM7Cs का उल्लेख करती है "अब तक कोई समर्पित अपलोडिंग समर्थन नहीं है, लेकिन कुछ को आपूर्ति करना काफी आसान होना चाहिए शेष टुकड़े खुद। " माथीस से, स्प्रे के लेखक (2012 से) – akauppi

+0

अकुप्पी एक संपादन का सुझाव देने के लिए स्वतंत्र महसूस करते हैं, मुझे अद्यतित उत्तरों पसंद हैं। क्या आपने इसे संकलित किया? – iwein

+0

आपका समाधान बाइनरी फ़ाइलों के लिए काम नहीं करता है, क्योंकि यह तारों के रूप में concatenation करता है। मैं एक उत्तर भेजूंगा जो बाइनरी के साथ भी काम करता है। – akauppi

2

ठीक है, बहुखण्डीय प्रपत्र डेटा के लिए एक स्प्रे Unmarshaller लिखने की कोशिश कर के बाद, मैं सिर्फ लिखने का फैसला किया एक स्केला HttpServlet कि अनुरोध पर कार्रवाई करने फ़ॉर्म प्रविष्टि प्राप्त होगा, और उपयोग अपाचे के FileUpload पुस्तकालय:

class FileUploadServlet extends HttpServlet { 

    override def doPost(request: HttpServletRequest, response: HttpServletResponse) { 
    val contentType = request.getContentType 
    val boundary = contentType.substring(contentType.indexOf("boundary=")+9) 
    val multipartStream = new MultipartStream(request.getInputStream, boundary) 

    // Do work with the multipart stream 
    } 

} 
+2

मैंने कॉमन्स-फ़ाइल अपलोड लोडिंग का उपयोग किया। स्प्रे के साथ संयोजन करना पागल imho है। – iwein

4

मैं नीचे दिए गए कोड का उपयोग कर समाप्त हो गया। बहुत कठिन नहीं था, लेकिन वास्तव में इस बारे में कहीं स्प्रे नमूना उपलब्ध होना चाहिए था।

multipart/form-data रूपों का उपयोग हमेशा किया जाना चाहिए (पारंपरिक application/x-www-form-urlencoded के बजाय) यदि बाइनरी अपलोड शामिल हैं। अधिक जानकारी here

मेरे आवश्यकताएं थीं: यथोचित बड़े आकार की बाइनरी फ़ाइलों को अपलोड करने

  • जरूरत
  • क्षेत्रों (या URL में नहीं एम्बेडेड अपलोड के फ़ाइल नाम)

कुछ सवाल के रूप में मेटाडाटा करना चाहते थे :

  • जिस तरह से मैं "सर्वोत्तम" तरीके से त्रुटियों का प्रबंधन कर रहा हूं?

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

post { 
    // Note: We cannot use a regular 'return' to provide a routing mid-way. The last item matters, but we can 
    // have a 'var' which collects the correct success/error info into it. It's a write-once variable. 
    // 
    var ret: Option[Route] = None 

    // Multipart form 
    // 
    // To exercise this: 
    // $ curl -i -F "[email protected]" -F "computer=MYPC" http://localhost:8080/your/route; echo 
    // 
    entity(as[MultipartFormData]) { formData => 
    val file = formData.get("file") 
     // e.g. Some(
     //  BodyPart(HttpEntity(application/octet-stream, ...binary data..., 
     //     List(Content-Type: application/octet-stream, Content-Disposition: form-data; name=file; filename=<string>))) 
    log.debug(s".file: $file") 

    val computer = formData.get("computer") 
    // e.g. Some(BodyPart(HttpEntity(text/plain; charset=UTF-8,MYPC), List(Content-Disposition: form-data; name=computer))) 
    log.debug(s"computer: $computer") 

    // Note: The types are mentioned below simply to make code comprehension easier. Scala could deduce them. 
    // 
    for(file_bodypart: BodyPart <- file; 
     computer_bodypart: BodyPart <- computer) { 
     // BodyPart: http://spray.io/documentation/1.1-SNAPSHOT/api/index.html#spray.http.BodyPart 

     val file_entity: HttpEntity = file_bodypart.entity 
     // 
     // HttpEntity: http://spray.io/documentation/1.1-SNAPSHOT/api/index.html#spray.http.HttpEntity 
     // 
     // HttpData: http://spray.io/documentation/1.1-SNAPSHOT/api/index.html#spray.http.HttpData 

     log.debug(s"File entity length: ${file_entity.data.length}") 

     val file_bin= file_entity.data.toByteArray 
     log.debug(s"File bin length: ${file_bin.length}") 

     val computer_name = computer_bodypart.entity.asString //note: could give encoding as parameter 
     log.debug(s"Computer name: $computer_name") 

     // We have the data here, pass it on to an actor and return OK 
     // 
     ...left out, application specific... 

     ret = Some(complete("Got the file, thanks.")) // the string doesn't actually matter, we're just being polite 
    } 

    ret.getOrElse(
     complete(BadRequest, "Missing fields, expecting file=<binary>, computer=<string>") 
    ) 
    } 
} 
+0

यह कोड 93 में दुर्घटना के बाद मेरे अंगूठे की तरह दिखता है, लेकिन आप इसे काम कर चुके हैं, और यह एक अपवित्र है। – iwein

+0

प्रक्रिया मेरे अंगूठे को हथियाने की तरह महसूस हुई थी। : पी प्रतिक्रिया कैसे मैं कोड को बेहतर बना सकता हूं इसकी सराहना की जाती है। – akauppi

1

पोस्ट (संभवतः बाइनरी) फ़ाइल हड़पने के लिए, और इसे कहीं अस्थायी रूप से चिपके रहते हैं, मैं इस प्रयोग किया है:

post { 
    entity(as[MultipartFormData]) { 
     formData => { 
     val ftmp = File.createTempFile("upload", ".tmp", new File("/tmp")) 
     val output = new FileOutputStream(ftmp) 
     formData.fields.foreach(f => output.write(f.entity.data.toByteArray)) 
     output.close() 
     complete("done, file in: " + ftmp.getName()) 
     } 
    } 
    }