2009-09-10 13 views
10

Mam sytuację, w której serwlet dostarcza skompresowane dane do skryptu PHP. Kompresuję dane po stronie Java bez problemu, ale wydaje się, że PHP nie jest w stanie rozpakować.Kompresja z dekompresją Javy za pomocą PHP

Oto kod dowiemy się z urywki Java Side:

OutputStream o=response.getOutputStream(); 

GZIPOutputStream gz=new GZIPOutputStream(o); 
gz.write(GridCoder.encode(rs,id, perPage, page).getBytes()); 
gz.close(); 
o.close(); 

PHP Side:

$xml= gzuncompress($xml); 

Może ktoś proszę wskaż mnie we właściwym kierunku.

+0

Czy pojawiają się błędy? czy możesz opublikować logi? – rogeriopvl

+0

Upewnij się, że kod JavaScript ustawia nagłówek HTTP 'Content-Encoding: gzip'. – Asaph

+0

Ostrzeżenie: gzuncompress(): błąd danych. Próbowałem po prostu echo danych bez próby rozpakowania go, aby upewnić się, że otrzymuję rzeczywiste dane i otrzymuję blok danych, który rozpoczyna: [ Content Content-Encoding jest ustawiony na gZip na Java Side .. –

Odpowiedz

9

Właśnie zobaczyłem twoje pytanie i byłem ciekaw tego. Zrobiłem więc własną próbę. Zostawiłem wszystkie rzeczy Servlet związanych z problemu i kodowane coś takiego:

import java.io.*; 
import java.util.zip.GZIPOutputStream; 

public class GZIPTestcase { 

    public static void main(String[] args) throws Throwable { 
     GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new FileOutputStream(new File("/Users/malax/foo2.gz"))); 
     PrintWriter pw = new PrintWriter(gzipOutputStream); 

     pw.println("All your base are belong to us!"); 
     pw.flush(); 
     pw.close(); 
    } 
} 

GNU gunzip była w stanie dekompresji danych. Następnie próbuję go rozpakować za pomocą PHP. Nie udało się z tym samym błędem, który otrzymałeś. Badałem dalej i znaleźć następujące metody:

  • gzdecode()
  • gzinflate()

gzinflate nie działa albo, gzdecode jest dostarczany tylko z PHP6 wich havn't zainstalowane. Może mógłbyś spróbować tego. (Zgodnie z http://bugs.php.net/bug.php?id=22123 to zadziała)

Mam wątpliwości, że problem jest po stronie Java, ponieważ GNU może zepsuć dane, więc musi być poprawne. Możesz chcieć zbadać dalej po stronie PHP.

Występuje prawdziwe pytanie do .NET i PHP, gdzie oryginalny plakat ma taki sam problem, jak masz: Can PHP decompress a file compressed with the .NET GZipStream class?. PHP wydaje się nie być w stanie rozpakować danych z .NET odpowiednik GZIPOutputStream albo.

Przepraszam, że nie mam "rozwiązania", ale i tak mogłem wskazać ci właściwy kierunek.

EDIT: znalazłem wpis w PHP Bugtracker która wyjaśnia problem: http://bugs.php.net/bug.php?id=22967 Wydaje się, że nie może gzuncompress rozpakowania danych GZIP z nagłówkami, które zostaną wyprodukowane być GZIPOutputStream. Jak podano w Wpisie na Bugtracker, spróbuj przyciąć nagłówek.

6

Spróbuj użyć DeflaterOutputStream zamiast GZIPOutputStream

PHP funkcje zadzwonić do libzlib który implementuje opróżnić. Gzip to zupełnie inna bestia.

Nazwanie funkcji PHP gz XXX tylko dodaje zamieszanie.

+0

To zadziałało dla mnie. – shady

+0

fajny, działa dobrze – radhoo

3

Znalazłem sposób, aby to naprawić, używając postu przez Devon_C_Miller i Malax jako wskazówki.

Kodeks Java:

String body = "Lorem ipsum shizzle ma nizle"; 

    URL url = new URL("http://some.url/file.php?id=" + uid); 
    URLConnection conn = url.openConnection(); 
    conn.setDoOutput(true); 
    conn.setRequestProperty("Content-encoding", "deflate"); 
    conn.setRequestProperty("Content-type", "application/octet-stream"); 

    DeflaterOutputStream dos = new DeflaterOutputStream(conn.getOutputStream()); 

    dos.write(body.getBytes()); 
    dos.flush(); 
    dos.close(); 

strona PHP:

$content = http_get_request_body(); 

    $uncontent = gzuncompress($content); 
+0

+1. Wypróbowałem wiele rozwiązań, w tym "wyciąć nagłówek nierozpoznany przez PHP", ale tylko to zadziałało. dzięki. – firebear

+0

która nie działa z ciągami, które mają po kompresji> 300b ... nie mają pojęcia dlaczego, ale w tych przypadkach 'DeflaterOutputStream' działa jak' GZIPOutputStream' (daje takie same wyniki, undecompressable przez PHP) –

+0

@FlashThunder Nie mogę odtworzyć swój problem za pomocą PHP 5.6.15 i Java 8. Jestem w stanie gzuncompress() w PHP o długości 1 miliona znaków losowego tekstu UTF-8 skompresowanego za pomocą Java DeflaterOutputStream (używając odpowiedzi podobnej do firebear). To 300KB skompresowane, a 1 MB skompresowane - znacznie przekraczające 300b. Oto kod używany do testowania Twojego błędu: https://gist.github.com/cordje/48a957333cd045afa3792c82334d9b06 –

0

Połączenie 'Java Deflater + PHP gzuncompress' pracował dla mnie. Klient: Android 4.1.1, witryna serwera: php 5.3

Dla tych, którzy szukają rozwiązania kompresji tylko części ciała żądania w niektórych przypadkach, na przykład jako ja, za pomocą formularza HTTP, aby opublikować niektóre parametry i plik, Oto fragment, którego używałem po stronie Androida:

public static byte[] compressString(String data) throws IOException { 
     byte[] compressed = null; 
     byte[] byteData = data.getBytes(); 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(byteData.length); 
     Deflater compressor = new Deflater(); 
     compressor.setLevel(Deflater.BEST_COMPRESSION); 
     compressor.setInput(byteData, 0, byteData.length); 
     compressor.finish(); 

     // Compress the data 
     final byte[] buf = new byte[1024]; 
     while (!compressor.finished()) { 
      int count = compressor.deflate(buf); 
      bos.write(buf, 0, count); 
     } 
     compressor.end(); 
     compressed = bos.toByteArray(); 
     bos.close(); 
     return compressed; 
    }