Загрузите zip-файл из PHP readfile() на Java


Я хочу загрузить zip-файл с помощью Java через HTTP и PHP. Мне это нужно, потому что мне нужен PHP, чтобы выполнить некоторую авторизацию, прежде чем я позволю пользователю загрузить.

После успешной авторизации страница отправляет файл с использованием этого кода:

if(file_exists($filename)){

    //Use Content-Disposition: attachment to specify the filename
    header("Content-type: application/zip");
    header('Content-Disposition: attachment; filename='.basename($filename));

    //No cache
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');

    //Define file size
    header('Content-Length: ' . filesize($filename));
    ob_clean();
    flush();
    echo "DOWNLOAD_START\r\n";
    readfile($filename);
    exit;
}else{
    clearstatcache();
    echo "No download available.";
}

Загрузка отлично работает при загрузке через браузер. Я проверяю, работает ли он нормально, просто пытаясь извлечь его. Приложение Java создает поврежденную версию.

Поскольку страница также выводит информацию о заголовке, я повторите "DOWNLOAD_START\r\n", чтобы указать, когда запускается zip-файл. Код, который загружает ZIP-файл:

InputStream sockin = keygenSock.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(sockin));
System.out.println("Reading...");
for(String line = reader.readLine(); line != null; line = reader.readLine()){
    System.out.println(line);
    if(line.startsWith("DOWNLOAD_START")){
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("contents.zip")));
        int read;
        int size = 0;
        byte[] buffer = new byte[2048];
        while((read = sockin.read(buffer, 0, 2048)) >= 0){
            size += read;
            bos.write(buffer, 0, read);
        }
        System.out.println("SIZE READ: " + size);
        bos.flush();
        bos.close();
        //zip(sockin);
        break;
    }
}

Фактический прочитанный байт не равен фактическому размеру файла в байтах. Итак, я предполагаю, что в том, как я загружаю ZIP-файл, есть ошибка?

Как я могу заставить Java-клиент загрузить zip-файл со страницы после авторизации?

Опять же, ошибка заключается в том, что загруженный ZIP-файл меньше, чем фактический ZIP-файл.

Спасибо.

РЕДАКТИРОВАТЬ: Если я просто сброшу все выходные данные в zip-файл, я смогу извлечь его с помощью WinRAR. Однако, если я открою его в текстовом редакторе, я смогу увидеть всю информацию о заголовке и "DOWNLOAD_START" перед фактическим zip-файлом. Это приводит к сбою классов распаковки Java (ZipInputStream и ZipEntry), поэтому мне нужно будет не включать их, даже если они будут правильно извлекаться с помощью программного обеспечения, такого как WinRAR.

Author: user2513924, 2016-07-09

1 answers

Проблема в буферизованном читателе, он будет считывать/потреблять больше, чем просто одну строку из потока.

Поэтому либо используйте небуферизованный считыватель. Это означает, что у вас нет метода чтения строки.

StringBuilder line = new StringBuilder();
int character;
while ((character = reader.read()) >= 0 && character != '\n') {
    line.append(character);
}

Или просто используйте то же самое с входным потоком.

StringBuilder line = new StringBuilder();
int character;
while ((character = stream.read()) >= 0 && character != '\n') {
    line.append(character);
}

Обе строки будут содержать \r, если он присутствовал (поэтому измените свой код соответствующим образом). До тех пор, пока используемая кодировка не испортит нижние 127 байт, с вами все будет в порядке в любом случае.

 1
Author: k5_, 2016-07-09 20:23:50