Java中使用HTTPClient进行GZip POST请求

16

我需要向一个包含压缩请求参数的 Web 服务器发送 POST 请求。我正在使用 Apache HttpClient,我已经读到它支持 Gzip 压缩,但我找不到任何关于如何完成我所需的内容的示例。如果有人能提供一些示例,我将不胜感激。


请问您能具体说明一下吗?"a gzipped string" 到底是指什么?是指一个经过 gzip 压缩的请求参数,还是指一个经过 gzip 压缩的请求体?您的服务器是否支持 gzip 压缩的请求?(并非所有服务器都支持...)您所了解的 HttpClient 透明支持 GZIP 的功能是针对 HTTP 响应而言,而不是针对 HTTP 请求。 - BalusC
哦,HTTPLib和HttpClient是不同的库... - BalusC
我已经编辑了我的问题。我的意思是HttpClient和一个gzip压缩的请求参数。谢谢。 - Alex Bliskovsky
仅一个压缩参数,而非整个请求体?你会如何发送它?作为Base64编码的参数值还是multipart/form-data部分?你确定目标服务器可以处理吗?服务器到底期望什么?或者服务器代码也完全由你控制吗? - BalusC
这将作为multipart/form-data请求的一部分。服务器期望一个压缩的参数。 - Alex Bliskovsky
好的,这个部分值的原始类型是什么?是 String 吗?是 File 吗?等等。 - BalusC
2个回答

19

首先,您需要将该String转换为压缩的byte[]或(临时)File。假设它不是非常大的String值,可以在可用的JVM内存中安全使用byte[]

String foo = "value";
ByteArrayOutputStream baos = new ByteArrayOutputStream();

try (GZIPOutputStream gzos = new GZIPOutputStream(baos)) {
    gzos.write(foo.getBytes("UTF-8"));
}

byte[] fooGzippedBytes = baos.toByteArray();

然后,您可以使用HttpClient将其作为多部分体发送,如下所示:

MultipartEntity entity = new MultipartEntity();
entity.addPart("foo", new InputStreamBody(new ByteArrayInputStream(fooGzippedBytes), "foo.txt"));

HttpPost post = new HttpPost("http://example.com/some");
post.setEntity(entity);

HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
// ...

请注意,HttpClient 4.1支持新的ByteArrayBody,可以按如下方式使用:

entity.addPart("foo", new ByteArrayBody(fooGzippedBytes, "foo.txt"));

在使用 WebView 时,这也是可能的吗? - RvdK
1
如果您假设POST的数据可能非常大,那么如何使用HTTPClient进行操作?我目前在低VM堆(16MB)设备上遇到了“内存不足”的问题。 - HGPB
这是一个很好的答案,但我仍然要抱怨使用最标准的Java库进行一行操作需要20行代码。 - djechlin
@HGPB,您需要启用多部分功能的分块请求。这样可以避免内存溢出。 - Arun George

0

尝试使用GzipCompressingEntity类。如果我要对帖子的主体进行压缩,例如JSON对象,我会按照下面的方式进行:

    // json payload
if (jsonBody != null) {
    
    post.setHeader("Content-Type", "application/json");
    StringEntity requestEntity = new StringEntity( jsonBody, ContentType.APPLICATION_JSON);
    
    if (gzipBody) {
        GzipCompressingEntity gzippedEntity = new GzipCompressingEntity(requestEntity);
        post.setEntity(gzippedEntity);
    }else {
        post.setEntity(requestEntity);
    }
    
}

还没有测试过,但我猜想如果要添加参数,你可以这样做:
    // add parameters
if (parameters != null && parameters.length > 0){

    List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
    for (int i = 0; i < parameters.length; i++){
        urlParameters.add(new BasicNameValuePair(parameters[i][0], parameters[i][1]));
    }
    post.setEntity(new GzipCompressingEntity(new UrlEncodedFormEntity(urlParameters)));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接