如何将使用 GZIP 压缩的字符串从 Java App 发送到 PHP Web 服务

Posted

技术标签:

【中文标题】如何将使用 GZIP 压缩的字符串从 Java App 发送到 PHP Web 服务【英文标题】:How to send string compressed with GZIP from Java App to PHP web service 【发布时间】:2015-03-27 08:03:24 【问题描述】:

我遇到了 GZIP 压缩问题:

我需要通过 POST 方法发送一个巨大的 JSON 字符串,它太大而无法像 URL 一样接受(例如:http://localhost/app/send/JSON STRING ENCODED BY BASE64),这会导致 HTTP 错误403

所以,我需要压缩我的 json,我找到了一种使用 GZIP 压缩的方法,我可以在 php 中使用 gzdecode() 进行解压缩。

但它不起作用......

我的函数 compress() 和 decompress() 在我的 Java 应用程序中工作正常,但是当我将它发送到 web 服务时,出现问题并且 gzdecode() 不起作用。 我不知道我错过了什么,我需要一些帮助

java 应用(客户端)中使用的函数

    public String Post()
     String retorno = "";
     String u = compress(getInput());
     u = URLEncoder.encode(URLEncoder.encode(u, "UTF-8"));

     URL uri = new URL(url + u);

     HttpURLConnection conn = (HttpURLConnection) uri.openConnection();

     conn.setDoOutput(false);
     conn.setRequestMethod(getMethod());

     conn.setRequestProperty("Content-encoding", "gzip");
     conn.setRequestProperty("Content-type", "application/octet-stream");

     BufferedReader buffer = new BufferedReader(
                    new InputStreamReader((conn.getInputStream())));

     String r = "";
     while ((r = buffer.readLine()) != null) 
                retorno = r + "\n";
     
     return retorno;

GZIP 压缩功能(客户端)

public static String compress(String str) throws IOException 

        byte[] blockcopy = ByteBuffer
                .allocate(4)
                .order(java.nio.ByteOrder.LITTLE_ENDIAN)
                .putInt(str.length())
                .array();
        ByteArrayOutputStream os = new ByteArrayOutputStream(str.length());
        GZIPOutputStream gos = new GZIPOutputStream(os);
        gos.write(str.getBytes());
        gos.close();
        os.close();
        byte[] compressed = new byte[4 + os.toByteArray().length];
        System.arraycopy(blockcopy, 0, compressed, 0, 4);
        System.arraycopy(os.toByteArray(), 0, compressed, 4,
                os.toByteArray().length);

        return Base64.encode(compressed);

    

用于接收 URL 的 php 方法(服务器,使用 Slim/PHP 框架)

init::$app->post('/enviar/:obj/', function( $obj ) 
     $dec = base64_decode(urldecode( $obj ));//decode url and decode base64 tostring
     $dec = gzdecode($dec);//here is my problem, gzdecode() doesn't work

发帖方式

public Sender() throws JSONException    
    //
    url = "http://192.168.0.25/api/index.php/enviar/";
    method = "POST";
    output = true;
    //

【问题讨论】:

不要使用str.getBytes();您没有指定编码。事实上,您也没有在发送的数据中指定它。 InputStreamReader 也一样。 如何为 InputStreamReader 指定编码? 通常情况下,the javadoc has the answer 好的,我应该使用常规的 UTF-8 编码或其他特定于 GZIP 压缩的编码? 选择编码与压缩无关;你当然会在压缩之前进行编码,但是你使用 UTF-8 + gzip(推荐)或者,谁知道,EBCDIC + compress,原理是一样的:字符 -> 字节流 -> 压缩字节流(然后在你的情况下用 BASE64 编码) 【参考方案1】:

正如在一些 cmets 中所注意到的那样。

    更大的数据应该作为 POST 请求而不是 GET 发送。 URL 参数应仅用于单个变量。正如您所注意到的,URL 长度被限制为几 kB,并且以这种方式发送更大的数据并不是一个好主意(即使 GZIP 压缩)。

    您的 GZIP 压缩代码似乎有误。请试试这个:

  public static String compress(String str) throws IOException 
    ByteArrayOutputStream os = new ByteArrayOutputStream(str.length());
    GZIPOutputStream gos = new GZIPOutputStream(os);
    gos.write(str.getBytes());
    os.close();
    gos.close();
    return Base64.encodeToString(os.toByteArray(),Base64.DEFAULT);
  

【讨论】:

纬线应该是:return Base64.encodeToString(os.toByteArray(),Base64.DEFAULT);

以上是关于如何将使用 GZIP 压缩的字符串从 Java App 发送到 PHP Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

Gzip压缩与解压

如何从 gzip 压缩文件转换为 Zstandard

Java利用Gzip对字符串进行压缩与解压

将 avro 文件压缩为 gzip (.gz) 压缩

如何连接两个或多个 gzip 文件/流

如何在 Java 中加速读写 base64 编码的 gzip 大文件