krasserm / grails-jaxrs

JAX-RS Plugin for Grails
http://code.google.com/p/grails-jaxrs/
Apache License 2.0
50 stars 48 forks source link

Multipart Form Data #61

Closed slackfarmer closed 8 years ago

slackfarmer commented 9 years ago

I was curious how one might go about creating an IntegrationTestSpec that would compose a multipartFormData request? Does anyone have an example of how to build up a multipart form object and convert it to bytes using this existing jaxrs framework?

Currently send request will only accept bytes as input

IntegrationTestSpec.groovy....



    @Override
    HttpServletResponse sendRequest(String url, String method, byte[] content) {
        defaultMixin.sendRequest(url, method, content)
    }

    HttpServletResponse sendRequest(String url, String method) {
        defaultMixin.sendRequest(url, method, ''.bytes)
    }

    @Override
    HttpServletResponse sendRequest(String url, String method, Map headers, byte[] content) {
        defaultMixin.sendRequest(url, method, headers, content)
    }

    HttpServletResponse sendRequest(String url, String method, Map headers) {
        defaultMixin.sendRequest(url, method, headers, ''.bytes)
    }


Jersey Client Example - how I might test multipart form using jersey client


    def static uploadTestAsset(String srcAsset, String destPath) {
        try {
            def asset = new File("./src/test/resources/${srcAsset}" as String)

            if (asset.exists()) {
                if (!destPath.startsWith('/')) {
                    destPath = "/${destPath}" as String
                }

                String endpoint = "http://localhost/api/repo/upload${destPath}" as String

                Client client = Client.create()
                WebResource webResource = client.resource(endpoint)

                def form = new FormDataMultiPart()
                form.field('filename', asset.getName())
                form.bodyPart(new FileDataBodyPart("fileUpload", asset, MediaType.APPLICATION_OCTET_STREAM_TYPE))

                def result = webResource
                        .type(MULTIPART_FORM_DATA)
                        .accept(V1_JSON)
                        .put(String.class, form)

                println "uploadTestAsset result: ${result}"
            }
        } catch (e) {
            e.printStackTrace()
        }
    }

slackfarmer commented 9 years ago

I figured out how to do it, by using an apache library(MultipartEntityBuilder) to compose the multipart body.

Added apache mime dependency


dependencies {
        compile('org.apache.httpcomponents:httpmime:4.4')
...

Body Building Code Sample

returns end point and a byte array


    public static Map getTestAssetProperties(String assetName){
        String destPath = "${REPO_TEST_ASSET_PATH}${assetName}"
        String endPoint = "/api/repo/upload/${destPath}"
        File asset = new File("./src/test/resources/${assetName}" as String)
        MultipartEntityBuilder e = new MultipartEntityBuilder()
        e.setBoundary("fnord")
        e.addTextBody('filename', asset.getName())
        e.addBinaryBody("fileUpload", asset)
        ByteArrayOutputStream baos = new ByteArrayOutputStream()
        e.build().writeTo(baos)
        return [endPoint:endPoint, bodyInBytes: baos.toByteArray()]
    }

Spock Test Example

Notice content type settings: ['Content-Type': 'multipart/form-data; boundary=fnord']


    def "Execute revisions request"() {
        setup:
        String assetName = "testAsset1.jpg" as String
        def assetProps = SetupTeardownUtils.getTestAssetProperties(assetName)
        // upload it five times
        for (i in 1..5) {
            def result = sendRequest(assetProps.endPoint,'PUT',['Content-Type': 'multipart/form-data; boundary=fnord'], assetProps.bodyInBytes)
            println "setup is uploading 5 test assets. Endpoint:[${assetProps.endPoint}] status:[${result.status}]"
        }
        when:
        sendRequest('/api/repo/revisions/test/static/asset/upload/testAsset1.jpg', 'GET', ['Content-Type': V1_JSON])
        then:
        response.status == 200
        response.contentAsString == '{"truncated":"false","status":{"success":"true"}}'
        response.getHeader('Content-Type').equals(V1_JSON)
        cleanup:
        println "deleting the 5 test assets"
    }
marciomalewschik commented 9 years ago

Hello slackfarmer,

Could you please help me sharing how you did your resource to accept a MultipartFile.

I'm using this plugin in this verison: compile ":jaxrs:0.11"

But until now I couldn't send a file to my resource.

In advance I thank you.

prabhatsubedi commented 8 years ago

hello @marciomalewschik I am too facing same problem. Did you find solution ?

budjb commented 8 years ago

This issue was moved to budjb/grails-jaxrs#21