Сжатие с помощью Java Decompressing с помощью PHP
У меня ситуация, когда сервлет предоставляет сжатые данные для PHP script. Я сжимаю данные на стороне Java без проблем, но PHP кажется неспособным распаковывать.
Ниже приведены соответствующие фрагменты кода Сторона Java:
OutputStream o=response.getOutputStream();
GZIPOutputStream gz=new GZIPOutputStream(o);
gz.write(GridCoder.encode(rs,id, perPage, page).getBytes());
gz.close();
o.close();
Сторона PHP:
$xml= gzuncompress($xml);
Может кто-нибудь, пожалуйста, назовите меня в правильном направлении.
Ответы
Ответ 1
Я только что увидел ваш вопрос и ему было любопытно. Поэтому я сделал свой собственный тестовый сценарий. Я оставил все связанные с Servlet вещи из проблемы и закодировал что-то вроде этого:
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 смог распаковать данные. Затем я пытаюсь распаковать его с помощью PHP. Это не удалось с той же ошибкой, что и вы. Далее я исследовал и нашел следующие методы:
gzinflate тоже не работает, gzdecode отправляется только с PHP6, который я не установил. Может быть, вы могли бы попробовать это. (Согласно http://bugs.php.net/bug.php?id=22123 это будет работать)
Я сомневаюсь, что проблема на стороне Java, потому что GNU gunzip может дефлировать данные, чтобы они были правильными. Возможно, вам захочется изучить дальнейшие действия на стороне PHP.
Существует нерешенный вопрос для .NET и PHP, где исходный плакат имеет ту же проблему, что и у вас: Может ли PHP распаковать файл, сжатый классом .NET GZipStream?. PHP, похоже, не способен распаковывать данные из .NET-эквивалента GZIPOutputStream.
Извините, что у меня нет "решения", но я, возможно, указал вам в нужном направлении.
EDIT: я нашел запись в PHP Bugtracker, которая объясняет проблему:
http://bugs.php.net/bug.php?id=22967 Кажется, что gzuncompress не может распаковать GZIP-данные с заголовками, которые будут созданы GZIPOutputStream. Как указано в записи Bugtracker, попробуйте обрезать заголовок.
Ответ 2
Попробуйте использовать DeflaterOutputStream вместо GZIPOutputStream
Функции PHP вызывают в libzlib, который реализует DEFLATE. Gzip совсем другой зверь.
Именование функций PHP gzXXX только добавляет к путанице.
Ответ 3
Я нашел способ исправить это, используя сообщение Devon_C_Miller и Malax в качестве рекомендаций.
Код для 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();
Сторона PHP:
$content = http_get_request_body();
$uncontent = gzuncompress($content);
Ответ 4
Сочетание "Java Deflater + PHP gzuncompress" работало для меня. Клиент: Android 4.1.1, сайт сервера: php 5.3
Для тех, кто ищет решение сжатия только частей тела запроса в некоторых случаях, например, как я, используя HTTP-форму для отправки некоторых параметров и файла, следующий фрагмент, который я использовал в стороне Android:
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;
}