问题描述:

I'm trying to test my Grails web application by creating and sending a multipart request from a stand-alone groovy test script that's built by gradle. But I'm struggling.

  • I can't attach a custom Content-ID header
  • I can't attach a file of random bytes created at runtime (I can attach an existing file, but I need many random files of varying size)

EDIT (Thanks to Xeon):

  • My script is now sending a valid multipart request, but my grails web app is not accepting any headers other than "Content-Type" for some reason.

Heres my code:

The Stand-Alone Test Script code:

void sendMultipartRequest(String url) {

HTTPBuilder httpBuilder = new HTTPBuilder(url)

httpBuilder.request(Method.POST){ req ->

MultipartEntityBuilder entityBuilder = new MultipartEntityBuilder()

entityBuilder.setBoundary("----boundary")

entityBuilder.setMode(HttpMultipartMode.RFC6532)

String randomString = myGenerateRandomStringMethod()

FormBodyPart formBodyPart = new FormBodyPart(

"SOME_NAME",

new InputStreamBody(new ByteArrayInputStream(randomString.bytes), "attachment", "SOME_NAME")

)

formBodyPart.addField("Content-ID", "abc123")

entityBuilder.addPart(formBodyPart)

response.success = { resp ->

println("Success with response ${resp.toString()}")

}

response.failure = { resp ->

println("Failure with response ${resp.toString()}")

}

delegate.setHeaders(["Content-Type":"multipart/related; boundary=----boundary"])

req.setEntity(entityBuilder.build())

}

}

Grails web-app side in the controller for handling posts:

def submitFiles() {

if(request instanceof MultipartHttpServletRequest){

HashMap<String, Byte[]> fileMap = extractMultipartFiles(request)

someService.doStuffWith(fileMap)

}

}

private HashMap<String, Byte[]> extractMultipartFiles(MultipartHttpServletRequest multipartRequest) {

HashMap<String, Byte[]> files = new HashMap<>()

for(element in mulipartRequest.multiFileMap){

MultipartFile file = element.value.first()

String contentId = multipartRequest.getMultipartHeaders(element.key).get("Content-ID")?.first()

if(contentId) files.put(contentId, file.getBytes())

}

return files

}

Libraries I'm using:

ext {

groovyVersion = "2.3.4"

commonsLangVersion = "2.6"

httpBuilderVersion = "0.7.1"

httpmimeVersion = "4.3.4"

junitVersion = "4.11"

}

dependencies {

compile "org.codehaus.groovy:groovy-all:${groovyVersion}"

compile "commons-lang:commons-lang:${commonsLangVersion}"

compile "org.codehaus.groovy.modules.http-builder:http-builder:${httpBuilderVersion}"

compile "org.apache.httpcomponents:httpmime:${httpmimeVersion}"

testCompile group: 'junit', name: 'junit', version: "${junitVersion}"

}

网友答案:

You can always use some subclass of ContentBody interface:

FormBodyPart(String name, ContentBody body) 

For example use: InputStreamBody:

new FormBodyPart("name", new InputStreamBody(new RandomInputStream(...)), ContentType.MULTIPART_FORM_DATA);

You can use: RandomInputStream class.

And with headers you could probably use: HTTPBuilder$RequestConfigDelegate.setHeaders(Map headers) because it's set to delegate of inner closure.

网友答案:

I've used curl in the past to do this testing:

curl -v -F "param1=1" -F "param2=99" -F "[email protected];type=video/x-flv" http://localhost:8080/someapp/sessions

somefile.flv is in the current directory

相关阅读:
Top