用于多部分数据的 Java http post

标签 java http post multipartform-data multipart

我正在使用 Apache HttpComponents v4.3.6(maven httpclient 和 httpmime)。我需要将文件数据作为多部分上传。有效的 Fiddler 命令如下所示。

Fiddler 上的请求 header :

Content-Type: multipart/form-data; boundary=c2d7073062e24d86ad739647574e14b9
Accept: application/json
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:22.0) Gecko/20100101 Firefox/22.0

Fiddler 上的请求正文:

--c2d7073062e24d86ad739647574e14b9
Content-Disposition: form-data; name="categoryFile"; filename="self-classification-categories.tsv"

585743  583099  Existing Catrali 4Category ch   Description of 4 Existing Category  false   false   false   Some notes 4 relating to Existing Category
--c2d7073062e24d86ad739647574e14b9--

文件的实际内容是:

585743  583099  Existing Catrali 4Category ch   Description of 4 Existing Category  false   false   false   Some notes 4 relating to Existing Category

现在,我正在尝试使用 Apache Http Client 实现此发布请求(如上所述),但不知道如何实际执行。为了将上述请求转换为Java(1.8),我尝试了:(边界值:c2d7073062e24d86ad739647574e14b9)

httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost( createPostURI( host, path ) );

httpPost.setHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:22.0) Gecko/20100101 Firefox/22.0");
httpPost.setHeader("Content-Type", "multipart/form-data; boundary=c2d7073062e24d86ad739647574e14b9");
httpPost.setHeader("Accept", "application/json");


String fileContent = "--c2d7073062e24d86ad739647574e14b9\r\nContent-Disposition: form-data; name=\"categoryFile\"; filename=\"self-classification-categories.tsv\""+
                "\r\n\r\n"+
                "585743 583099  Existing Catrali 4Category ch   Description of 4 Existing Category  false   false   false   Some notes 4 relating to Existing Category"
                +"\r\n--c2d7073062e24d86ad739647574e14b9--";

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.setBoundary("c2d7073062e24d86ad739647574e14b9");
builder.addTextBody("body", fileContent,ContentType.MULTIPART_FORM_DATA);

HttpEntity entity =  builder.build();
httpPost.setEntity( entity );

response = httpclient.execute( httpPost, new GenericResponseHandler() );

我确信我在 Java 中制作请求主体的方式是错误的。因此,我看到 403 错误,这有点误导,因为我调用的 REST api 会抛出此错误当它没有看到预期的格式时。我将不胜感激任何帮助。

提前致谢。

最佳答案

由于我从 fiddler 获得了成功的交易,因此我将 fiddler 与 eclipse 集成,以找出通过 java 代码进行 api 调用所造成的差异。最后,使用这段代码成功了:

public GenericResponse processHttpPostRequest( String host, String path,String content, Map<String, String> parameters, String multiPartDataBounadry ,String outfilePath)
{
    CloseableHttpClient httpclient = null;

    GenericResponse response = null;
    try
    {
        //This is important to integrate eclipse with fiddler
        HttpHost proxy = new HttpHost("localhost", 8888);

        HttpPost httpPost = new HttpPost( createPostURI( host, path,parameters) );


        setHeader(multiPartDataBounadry, httpPost);

        //This is important to integrate eclipse with fiddler
        httpclient = HttpClients.custom().setProxy(proxy).disableContentCompression().build(); 
        //httpclient = HttpClients.createDefault();

        HttpEntity entity = setRequestBody(content, multiPartDataBounadry);

        httpPost.setEntity( entity );

        LOGGER.info( "Executing request URI " + httpPost.getURI() );

        response = httpclient.execute( httpPost, new GenericResponseHandler() );
        handleResponse(response, outfilePath);

        if (response.getStatusCd() != 200)
        {
            handleResponseError(parameters, response);
        }

    }
    catch(Throwable e)
    {
        e.printStackTrace();
        throw new RuntimeException(e);
    }

    finally
    {
        closeClient(httpclient);
    }

    return response;
}

private void setHeader(String multiPartDataBounadry, HttpEntityEnclosingRequestBase httpEntity) 
{
    httpEntity.setHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:22.0) Gecko/20100101 Firefox/22.0");
    httpEntity.setHeader("Content-Type", "multipart/form-data; boundary="+multiPartDataBounadry);
    httpEntity.setHeader("Accept", "application/json");
}

private HttpEntity setRequestBody(String content, String multiPartDataBounadry) 
{
    FormBodyPart bodyPart = FormBodyPartBuilder.create()                    
            .setName("any_name")
            .addField("Content-Disposition", "form-data; name=\"categoryFile\"; filename=\"self-classification-categories.tsv\"")
            .setBody(new StringBody(content, ContentType.MULTIPART_FORM_DATA))
            .build();

    MultipartEntityBuilder builder = MultipartEntityBuilder.create()
            .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
            .setBoundary(multiPartDataBounadry)
            .addPart(bodyPart);

    HttpEntity entity =   builder.build();

    return entity;

}


private URI createPostURI( String host, String path , Map<String, String> parameters) throws Exception
{
    URI finalURL = null;
    try
    {
        URIBuilder url = null;
        url = new URIBuilder();
        url.setScheme( "http" );
        url.setHost( host );
        url.setPath( path );
        url.setParameter("first_param", "first_param_value");
        url.setParameter("second_param","second_param_value");

        finalURL =  url.build() ;

    }
    catch ( URISyntaxException |  IllegalArgumentException  e )
    {
        e.printStackTrace();
        throw e;
    }

    return finalURL;
}

关于用于多部分数据的 Java http post,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37371397/

相关文章:

java - 读取 JAR 文件内的文件

apache - 自制软件网站的自定义禁止页面

javascript - 在客户端处理 WebSocket 404

c# - 如何使用ajax发送字典和文件

javascript - 如何在 IE6 上监视来自 Javascript 的所有 XmlHttpRequest POST?

iOS NSURLSession,如何在 didCompleteWithError 中重试

java - 如何更改 Jason-JEdit 生成的进程的 java 内存堆量? [Linux]

java - 编译 fatal error : invalid flag: --release for jdk 11 on Jenkins?

Gitlab 6.2 在推送到源时要求用户名和密码身份验证

java - 局部内部类是否在定义它们的范围内维护所有局部变量的副本?