问题
I need to form a 'multipart/form-data' REST request with jpeg image and JSON file as the content.I am stuck with encoding the 'multipart/form-data' as a zip file.
Can someone tell me, how I can achieve this with groovy RESTClient? I could not find any documentation regarding this.
回答1:
As it can be seen in the docs RESTClient
extends HTTPBuilder
. HTTPBuilder
has a getEncoder
method that can be used to add dedicated encoder (with type and method). See the following piece of code:
import org.codehaus.groovy.runtime.MethodClosure
import javax.ws.rs.core.MediaType
//this part adds a special encoder
def client = new RESTClient('some host')
client.encoder.putAt(MediaType.MULTIPART_FORM_DATA, new MethodClosure(this, 'encodeMultiPart'))
//here is the method for the encoder added above
HttpEntity encodeMultiPart(MultipartBody body) {
MultipartEntityBuilder.create()
.addBinaryBody(
'file',
body.file,
ContentType.MULTIPART_FORM_DATA,
body.filename
).build()
}
//here's how MultipartBody class looks:
class MultipartBody {
InputStream file
String filename
}
Now to create a multipart request You need to pass an instance of MultipartBody
as a body argument to the request.
回答2:
Realise this is an oldy but might help others, although the question answers it from a beginner point of view it is difficult to fully understand how to reuse all of above properly.
Firstly the last comment on the question points to this link :
Which attempts to re-use the answer incorrectly. It has mixed above answer with an answer from this link
def content1 = new ContentDisposition("filename=aa.json")
def json1 = new File("resources/aa.json")
def attachments1 = new Attachment("root", new ByteArrayInputStream(json1.getBytes()), content1)
InputStream is2 = getClass().getResourceAsStream("resources/aa.json");
InputStream is1 = getClass().getResourceAsStream("resources/img.png");
ContentDisposition content2 = new ContentDisposition("attachment;filename=img.png")
Attachment attachments2 = new Attachment("root1", is1, content2)
def attachments = [attachments1, attachments2]
def body1 = new MultipartBody(attachments)
def client = new RESTClient( "https://somehost.com" )
ocutag.encoder.putAt(MediaType.MULTIPART_FORM_DATA, new MethodClosure(this, 'encodeMultiPart1'))
ocutag.encoder.putAt(MediaType.MULTIPART_FORM_DATA, new MethodClosure(this, 'encodeMultiPart2'))
The above is never going to work, I have it working like so:
def http = new RESTClient('http://localhost:8080')
http.encoder.putAt(MediaType.MULTIPART_FORM_DATA, new MethodClosure(this, 'encodeMultiPart'))
def body1 = new MultipartBody() //This is that MultipartBody class in the first answer example not the one from your imports......
body1.file=file.getInputStream()
body1.filename=file.name
def response = http.put( path: url, body:body1, query:['query':action, ], requestContentType: 'multipart/form-data' )
You also have encodeMultiPart2 and encodeMultiPart1, I think this is a misunderstanding just reuse 1 declaration of this method in both cases.. you don't need to do none of the attachments etc you have in your example..
回答3:
Encoder registrations are so messy in previous responses, here is my working example:
import org.apache.cxf.jaxrs.ext.multipart.Attachment
import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import javax.ws.rs.core.MediaType
...
def filenameToUpload = "doggo.jpg"
def expectedRequestParamName = "file"
def static uploadFile() {
// create attachment
def fileToUpload = new File(filenameToUpload)
def attachment = new Attachment(expectedRequestParamName, new ByteArrayInputStream(fileToUpload.getBytes()), new ContentDisposition("filename=" + filenameToUpload))
def body = new MultipartBody(attachment)
// create REST client
def httpClient = new RESTClient('http://localhost:8080')
// register encoder
httpClient.encoder.putAt(MediaType.MULTIPART_FORM_DATA, customMultipartEncoder)
// call REST
httpClient.post(
path: "upload",
body: body,
requestContentType: MediaType.MULTIPART_FORM_DATA)
}
// register multipart encoder
private def static customMultipartEncoder = { body ->
def builder = MultipartEntityBuilder.create()
body.allAttachments.collect {
builder.addBinaryBody(
it.contentId,
it.dataHandler.inputStream,
ContentType.MULTIPART_FORM_DATA,
it.contentId) }
return builder.build()
}
来源:https://stackoverflow.com/questions/28870172/encoder-function-for-multipart-form-data-in-groovy