согласно домашней странице BalusC, я реализовал функцию downloadPDF()
, которая считывает PDF файл из файловой системы и отображает его в браузере. эта функция работает по назначению.
кроме того, у меня есть класс EncryptionService
, который позволяет мне шифровать и/или расшифровывать данный файл. это также работает по назначению.
к сожалению, не представляется возможным читать PDF файл, расшифровывать его и отображать в браузере. он заканчивается тем, что браузер пытается загрузить файл снова и снова, не показывая ничего вообще.
приведенный ниже код показывает мои простые модификации обработчика BalusC PDF.
public void showDocument(String path, boolean decrypt) throws IOException, InvalidKeyException {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
File file = new File(path);
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
if(!decrypt)
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
else {
// update MessageDigets, return Key
cipher.init(Cipher.DECRYPT_MODE, genKey(passphrase));
input = new BufferedInputStream(new CipherInputStream(new FileInputStream(file), cipher), DEFAULT_BUFFER_SIZE);
}
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + path + "\"");
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
} finally {
try {
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
facesContext.responseComplete();
}
Что происходит
Как и ошибка консоли,
нетто :: ERR_CONTENT_LENGTH_MISMATCH
Это указывает, что фактический размер содержимого, возвращаемого в тело ответа, не соответствует размеру, указанному в заголовке Content-Length
ответа.
Почему это происходит
Причина несоответствия распределяется по двум факторам:
Шифрование обычно увеличивает размер зашифрованного контента. Процесс шифрования требует обфускации содержимого с помощью шифрования, который обычно означает бросание в материал, из-за чего содержимое неприменимо в противном случае. Расшифровка, с другой стороны, вернет содержимое оригинальному размеру
Браузеры подвержены кэшированию. Если вы достаточно часто используете разные файлы (используя одно и то же имя файла), ваш браузер, скорее всего, просто решит, что он тот же файл с тем же контентом и просто обслуживает кешированную версию файла. В вашем случае вы объявляете ссылку на зашифрованный файл, получаете доступ к файлу, дешифруете его и затем записываете дешифрованное содержимое обратно в тот же дескриптор файла для зашифрованной версии.
Диск-ввод-вывод не является 100% -ным шагом с ОЗУ или ЦП. Запись на диск и чтение с диска по-прежнему несет накладные расходы в виде RAM, ожидающего диск.
Исправить
Создайте случайное/различное имя файла для каждого из файлов, участвующих в вашей операции. Это означает отдельное имя файла для зашифрованного контента и отдельное для расшифрованной формы
Как следствие вышеизложенного, откройте разные выходные потоки для разных файлов, также используя разные переменные доступа к File
.
Связанный:
showDocument
ли выполнениеshowDocument
? Что отправлено обратно в браузер? Посмотрите на вкладке сети вашего браузера, чтобы увидеть код ответа, заголовки и пакет тела ответаshowDocument
завершается правильно. вкладка сети ничего не показывает, когда я загружаю что-то в новую вкладку. он показывает system.jsf (текущий сайт) при попытке загрузить в той же вкладке. через несколько секунд это приводит к ошибкеnet::ERR_CONTENT_LENGTH_MISMATCH
.