Главная Библиотека Шаблоны и примерыЗадача Domino HTTP. Агент Скачать файлы одним архивом и обработка отдаваемых пользователю файлов. Часть вторая
Краткое содержание предыдущей части
На пути к решению "дела на одну трубку" встают всё новые и новые проблемы. Герой их преодолевает с завидной лёгкостью, пока не приходит в засаду, выбраться из которой помогут лишь отчаянные средства. Иль никакие
Николай Норкин
г. Киров
notesnet@notesnet.ru
На нашем пути к решению опять, как и в прошлый раз (Обработка загружаемых файлов сервлетом UploadProcess. Часть первая), встала web-engine Domino. В прошлом решении препятствие удалось обойти, перенеся обработку на сервлет. Аналогично попробуем обмануть преграду и в данном решении
Агент на этот раз остаётся частью решения, так как его посредством будет контролироваться доступ к документу. Но выходной поток будет не бинарным, а в кодировке base64, благодаря чему он благополучно преодолеет web-engine Domino. Промежуточным звеном между пользователем и web-engine станет сервлет DownloadProcess, в чьи функции будут входить следующие задачи:
- приём запроса от браузера и перенаправление его на Web-engine Domino
- получение ответа от engine Domino
- перекодировка потока из base64 в бинарный формат
- и, наконец, антивирусная проверка
К сожалению, на призыв автора поделиться success story использования антивирусного решения, добровольцев не нашлось, эту тему придётся оставить до более светлого будущего
Обо всём же остальном речь пойдёт прямо сейчас
Вывод результата работы агента
Описание агента в прошлой части прервалось на строке получения zip-архива
this.stream = this.getAgentOutputStream();
java.io.ByteArrayOutputStream zip = this.getPack(document);
продолжим с этого места
String base64 = javax.xml.bind.DatatypeConverter.printBase64Binary(zip.toByteArray());
this.stream.write("Content-Type:application/zip\n".getBytes());
this.stream.write("Content-Disposition: attachment; filename*=utf-8''%D0%9E%D0%B4%D0%BD%D0%B8%D0%BC%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%BC.zip\n".getBytes()); // Одним файлом.zip
this.stream.write("Content-Transfer-Encoding: base64\n".getBytes());
this.stream.write(("Content-Length: ".concat(Long.toString(base64.length())).concat("\n")).getBytes());
this.stream.write(base64.getBytes());
zip.flush();
zip.close();
} catch(Exception e) {
e.printStackTrace();
}
finally {
try {this.stream.flush();} catch(Exception e) {}
try {this.stream.close();} catch(Exception e) {}
}
}
Полностью код агента в архиве zip-download.src.zip
Настройка серверных правил
Для простоты обращения создадим документы web-правил для сайта
Для агента
Basics |  |
Description: |  |
Type of rule: | Substitution |
Incoming URL pattern: | /edu/*.zip |
Replacement pattern: | /www/education.nsf/zip-download?openagent&id=* |
и для сервлета
Basics |  |
Description: |  |
Type of rule: | Substitution |
Incoming URL pattern: | /download/* |
Replacement pattern: | /servlets/downloadProcess?url=http://mysite.com/* |
Теперь для обращения к сервлету будет использован URL /download/edu/идентификатор_документа.zip. Сервлет будет транслировать его агенту на адрес /edu/идентификатор_документа.zip вашего сайта
И, на всякий случай, во избежание шуток с рекурсией
Basics |  |
Description: |  |
Type of rule: | Substitution |
Incoming URL pattern: | /download/download/* |
Replacement pattern: | /0.gif |
Сервлет DownloadProcess
Итак, сервлет принимает пользовательский запрос и перенаправляет его на адрес, заданный параметром URL get-запроса
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
java.io.InputStream stream = this.getResponse(request, response);
}
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
doGet(request, response);
}
protected java.io.InputStream getResponse(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) {
java.net.HttpURLConnection connection = null;
java.net.URL url = null;
try {
java.io.OutputStream reqStream = null;
java.io.InputStream resStream = null;
String host = request.getHeader("HOST");
String parameter = request.getQueryString();
String address = this.getAddress(parameter);
url = new java.net.URL(address);
connection = (java.net.HttpURLConnection) url.openConnection();
java.util.Enumeration _unum = request.getHeaderNames();
while (_unum.hasMoreElements()) {
String headerName = (String)_unum.nextElement();
String headerValue = request.getHeader(headerName);
connection.setRequestProperty(headerName, headerValue);
}
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches (false);
connection.setRequestMethod("GET");
}
catch (Exception e) {
response.setStatus(500);
return null;
}
.....
После того, как пришёл ответ от сервера, сервлет прозрачно возвращает этот ответ пользователю (пока мы ещё не добрались до антивирусной проверки), или, если ответ пришёл в кодировке base64, преобразует ответ в бинарный вид перед тем, как опять же, отдать его пользователю
int responseCode = connection.getResponseCode();
response.setStatus(responseCode); // передача статуса ответа
String header = null; // чтение заголовков с передачей их web-пользователю
try { header = connection.getHeaderField("Content-Type");} catch (Exception e) {}
if (header != null)
response.setContentType(header);
header = null;
try { header = connection.getHeaderField("Content-Disposition");} catch (Exception e) {}
if (header != null)
try { response.setHeader("Content-Disposition", header);} catch (Exception e) {}
header = null;
try { header = connection.getHeaderField("Content-Transfer-Encoding");} catch (Exception e) {}
// а этот заголовок установлен агентом и требует перекодировки в binary
if (header != null && header.equalsIgnoreCase("base64")) {
try { response.setHeader("Content-Transfer-Encoding", "binary");} catch (Exception e) {}
byte[] bytes = this.streamToByteArray(connection.getInputStream());
byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(new String(bytes));
try { response.setContentLength(decoded.length);} catch (Exception e) {}
java.io.OutputStream outputStream = response.getOutputStream();
outputStream.write(decoded);
}
else {
if (header != null)
try { response.setHeader("Content-Transfer-Encoding", header);} catch (Exception e) {}
header = null;
try { header = connection.getHeaderField("Content-Length");} catch (Exception e) {}
if (header != null)
try { response.setContentLength(Integer.parseInt(header));} catch (Exception e) {}
if (responseCode == java.net.HttpURLConnection.HTTP_OK){
java.io.InputStream stream = connection.getInputStream(); // поток ответа переписывается в возвращаемый пользователю поток
byte[] buffer = new byte[20*1024];
java.io.OutputStream outputStream = response.getOutputStream();
while(true) {
int readSize = stream.read(buffer);
if(readSize==-1)
break;
outputStream.write(buffer,0,readSize);
}
}
}
}
catch (Exception e) {}
finally {
if (connection != null){
connection.disconnect();
}
}
return null;
}
Ну, вот и всё. Решение готово. Архив с кодом сервлета можно скачать
Ссылки
Задача Domino HTTP. Агент Скачать файлы одним архивом и обработка отдаваемых пользователю файлов. Часть первая
Задача Domino HTTP. Обработка загружаемых файлов сервлетом UploadProcess
Код агента zip-download
Код сервлета DownloadProcess
Пакет commons-codec-1.7.jar (для работы с base64)
|
Опубликовано — 03/03/2021 |
| |
|
|