Загрузите 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.
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 байт, с вами все будет в порядке в любом случае.