2012-06-05 17 views
8

का उपयोग करके MultipartFormData को पोस्ट करने के लिए कैसे करें जावा एचटीपी अनुरोध में, हम multipart HTTP पोस्ट बनाने के लिए ऐसा कर सकते हैं।प्ले 2.0 WS.url या WS.WSRequest

HttpClient httpclient = new DefaultHttpClient(); 
HttpPost httppost = new HttpPost(url); 

FileBody bin = new FileBody(new File(fileName)); 
StringBody comment = new StringBody("Filename: " + fileName); 

MultipartEntity reqEntity = new MultipartEntity(); 
reqEntity.addPart("bin", bin); 
reqEntity.addPart("comment", comment); 
httppost.setEntity(reqEntity); 

HttpResponse response = httpclient.execute(httppost); 
HttpEntity resEntity = response.getEntity(); 

मैं WS.url या WS.WSRequest का उपयोग करके इसे कैसे प्राप्त कर सकता हूं?

WSRequestHolder wsReq = WS.url("http//url");    
wsReq.setHeader("Content-type", "multipart/form-data"); 

उत्तर

5

यह मैला है, और निश्चित रूप से साफ किया जा सकता है, लेकिन यह है कि मैंने इसे काम करने के लिए क्या किया। इसे इतना बेहतर बनाने के लिए स्वतंत्र महसूस करें।

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 

import play.libs.WS; 

import com.ning.http.multipart.FilePart; 
import com.ning.http.multipart.MultipartRequestEntity; 
import com.ning.http.multipart.Part; 

ByteArrayOutputStream bos = new ByteArrayOutputStream(); 

// Build up the Multiparts 
List<Part> parts = new ArrayList<>(); 
parts.add(new FilePart("file", new File(filename))); 
Part[] partsA = parts.toArray(new Part[parts.size()]); 

// Add it to the MultipartRequestEntity 
MultipartRequestEntity reqE = new MultipartRequestEntity(partsA, null); 
reqE.writeRequest(bos); 
InputStream reqIS = new ByteArrayInputStream(bos.toByteArray()); 
WS.WSRequestHolder req = WS.url(InterchangeConfig.conflateUrl+"dataset") 
    .setContentType(reqE.getContentType()); 
req.post(reqIS).map(...); 
// or req.post(reqIS).get(); 

यह सब प्ले 2.0 ढांचे में पहले से ही टुकड़ों का उपयोग कर रहा है।

+0

यह हमारे लिए प्ले 2.2 में काम करता है, लेकिन लगता है कि Play play में टूटा हुआ है ... 'play.libs.ws' परिवर्तन को ठीक करने के बाद भी। किसी भी अनुमान की सराहना क्यों करें। –

+0

@EricWilson क्या आप "टूटा" से अधिक विशिष्ट हो सकते हैं? – nafg

+0

क्षमा करें, मैं अब और खेल के साथ काम नहीं करता हूं, और उस कोड तक पहुंच नहीं है। –

0

ऐसा लगता है कि प्ले एपीआई दस्तावेज के आधार पर, मल्टीपार्ट पोस्ट निकायों के लिए कोई अंतर्निहित नहीं है।

हालांकि, यह अपनी पसंद का एक प्रकार टी के साथ विधि

post[T](body: T)(implicit wrt: Writeable[T], ct: ContentTypeOf[T]): Future[Response] 

उपयोग कर अपने खुद बहुखण्डीय शरीर बनाने के लिए संभव हो सकता है, और भी इसी लेखनीय और ContentTypeOf प्रकार के।

लेकिन यह यह बताएगा कि मल्टीपार्ट निकायों HTTP के साथ कैसे काम करते हैं।

+0

क्या आप एक उदाहरण साझा कर सकते हैं? – angelokh

+0

असल में, मैंने आपको स्कैला एपीआई दिखाया है, और आप जावा का उपयोग करना चाहते हैं, क्षमा करें। जावा में, एक पोस्ट (इनपुटस्ट्रीम) विधि है। हो सकता है कि आप इनपुट स्ट्रीम में सही सामग्री बना सकें :) –

+0

@angelokh: यहां एक उदाहरण दिया गया है: http://cdmckay.org/blog/2015/06/24/how-to-add-support-for- पोस्टिंग- मल्टीपार्ट-फॉर्म-टू-द-प्ले-स्कैला-डब्ल्यूएस-लाइब्रेरी/ – cdmckay

3

बाह्य पुस्तकालयों पर भरोसा किए बिना, अब के लिए एकमात्र समाधान मैन्युअल रूप से मल्टीपार्ट फॉर्म डेटा अनुरोध बना रहा है। यह एक उदाहरण है कि यह कैसे, किया जा सकता है play.libs.WS.url का उपयोग कर:

WSRequestHolder wsRequestHolder = WS.url(URL); 

String boundary = "--XYZ123--"; 

String body = ""; 
for (String key : data.keySet()) { 
    body += "--" + boundary + "\r\n" 
     + "Content-Disposition: form-data; name=\"" 
     + key + "\"\r\n\r\n" 
     + data.get(key) + "\r\n"; 
} 
body += "--" + boundary + "--"; 

wsRequestHolder.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary); 
wsRequestHolder.setHeader("Content-length", String.valueOf(body.length())); 

wsRequestHolder.post(body); 

data एक java.util.Map<String, String> सभी नाम/मान युग्म आप फार्म पैरामीटर के रूप में पारित करने के लिए चाहते हैं होगा। अनुरोध से अनुरोध में सीमा बदलने के लिए randomString एक यादृच्छिक मान है। बाइनरी डेटा जोड़ना वैसे ही काम करेगा।

यह http://www.htmlcodetutorial.com/forms/form_enctype.html चश्मा को समझने के लिए संदर्भित करने के लिए एक अच्छी जगह है।

0

जैसा कि रोमैन सर्टेलन ने सुझाव दिया था, आप इस मामले को संभालने के लिए एक लिखने योग्य लिख सकते हैं। यहाँ एक है मैं ने लिखा है:

package utilities 

import java.io.{ByteArrayOutputStream, File} 

import com.ning.http.client.FluentCaseInsensitiveStringsMap 
import com.ning.http.multipart.{MultipartRequestEntity, FilePart, StringPart} 
import play.api.http.HeaderNames._ 
import play.api.http.{ContentTypeOf, Writeable} 
import play.api.mvc.{Codec, MultipartFormData} 

object MultipartFormDataWriteable { 

    implicit def contentTypeOf_MultipartFormData[A](implicit codec: Codec): ContentTypeOf[MultipartFormData[A]] = { 
     ContentTypeOf[MultipartFormData[A]](Some("multipart/form-data; boundary=__X_PROCESS_STREET_BOUNDARY__")) 
    } 

    implicit def writeableOf_MultipartFormData(implicit contentType: ContentTypeOf[MultipartFormData[File]]): Writeable[MultipartFormData[File]] = { 
     Writeable[MultipartFormData[File]]((formData: MultipartFormData[File]) => { 

      val stringParts = formData.dataParts flatMap { 
       case (key, values) => values map (new StringPart(key, _)) 
      } 

      val fileParts = formData.files map { filePart => 
       new FilePart(filePart.key, filePart.ref, filePart.contentType getOrElse "application/octet-stream", null) 
      } 

      val parts = stringParts ++ fileParts 

      val headers = new FluentCaseInsensitiveStringsMap().add(CONTENT_TYPE, contentType.mimeType.get) 
      val entity = new MultipartRequestEntity(parts.toArray, headers) 
      val outputStream = new ByteArrayOutputStream 
      entity.writeRequest(outputStream) 

      outputStream.toByteArray 

     })(contentType) 
    } 

} 

इसका इस्तेमाल करने के तरीके:

import utilities.MultipartFormDataWriteable._ 

... 

val url = "https://example.com" 

val dataParts = Map(
    "foo" -> Seq("bar"), 
    "alice" -> Seq("bob") 
) 

val file = new jave.io.File(... path to a jpg ...) 
val fileParts = Seq(new FilePart("attachment", "foo.jpg", Some("image/jpeg"), file) 

val multipartFormData = MultipartFormData(dataParts, fileParts, Seq(), Seq()) 

WS.url(url).post(multipartFormData) 
+0

वास्तव में बहुत अच्छा विचार! हालांकि, यह अब संकलित नहीं है। क्या आपका मतलब है 'com.ning.http.client.multipart आयात करें ...'? साथ ही, 'stringParts ++ fileParts' एक सेक [फ़ाइलपार्ट] में स्ट्रिंगपार्ट जोड़ता है, जिससे एक सेक [बेसपार्ट] होता है। 'MultipartRequestEntity' को एक उपयोग की आवश्यकता है। सूची [भाग] (एक ऐरे नहीं [पार्टबेस])। क्या यह आपके लिए नवीनतम प्ले रिलीज 2.4.6 में संकलित है? –

3

कार्य उदाहरण खेलने 2.3 के लिए दृष्टिकोण से ऊपर का उपयोग कर, यह भी contentType फ़ाइल अपलोड करते समय जोड़ा।

public Promise<WSResponse> upload(Http.MultipartFormData.FilePart policyFilePart, String contentType) { 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    List<Part> parts = new ArrayList<>(); 
    try { 
     parts.add(new FilePart("file", policyFilePart.getFile(), contentType, null)); 
     parts.add(new StringPart("param1", "value1")); 
     parts.add(new StringPart("param2", "value2")); 
     Part[] partsA = parts.toArray(new Part[parts.size()]); 

     // Add it to the multipart request entity 
     MultipartRequestEntity requestEntity = new MultipartRequestEntity(partsA, new FluentCaseInsensitiveStringsMap()); 
     requestEntity.writeRequest(bos); 
     InputStream reqIS = new ByteArrayInputStream(bos.toByteArray()); 
     return WS.url(baseUrl + "upload") 
       .setContentType(requestEntity.getContentType()) 
       .post(reqIS).map(new Function<WSResponse, WSResponse>() { 
        @Override 
        public WSResponse apply(WSResponse wsResponse) throws Throwable { 
          return wsResponse; 
        } 
       }); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 
+0

समाधान के लिए एक लिंक का स्वागत है, लेकिन कृपया सुनिश्चित करें कि आपका उत्तर इसके बिना उपयोगी है: [लिंक के चारों ओर संदर्भ जोड़ें] (// meta.stackexchange.com/a/8259) ताकि आपके साथी उपयोगकर्ताओं को कुछ पता चल जाएगा कि यह क्या है और यह वहां क्यों है, फिर लक्ष्य पृष्ठ अनुपलब्ध होने पर आप जिस पृष्ठ से लिंक कर रहे हैं उसके सबसे प्रासंगिक भाग को उद्धृत करें। [उत्तर जो किसी लिंक से थोड़ा अधिक हटाए जा सकते हैं।] (// stackoverflow.com/help/deleted-answers) –

+0

@ एमएआर। मैंने लिंक हटा दिया है, इसके बजाय मैंने यहां कोड लिखा है केवल –

+0

धन्यवाद! काफी बेहतर। –

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