При программной отправке формы, сгенерированной JSF, необходимо убедиться, что вы учли следующие 3 вещи:
- Поддерживать сеанс HTTP (конечно, если на веб-сайте включено сохранение состояния на стороне сервера JSF).
- Отправьте пару имя-значение скрытого поля
javax.faces.ViewState
.
- Отправьте пару «имя-значение» кнопки, которая должна быть фактически нажата.
В противном случае действие, возможно, вообще не будет запущено. Для остатка он ничем не отличается от «обычных» форм. Поток в основном выглядит следующим образом:
- Отправьте запрос GET на страницу с формой.
- Извлеките файл cookie JSESSIONID.
- Извлечь значение скрытого поля
javax.faces.ViewState
из ответа. При необходимости (наверняка, если оно имеет динамически генерируемое имя и, следовательно, возможно, меняет каждый запрос), хорошо извлеките имя поля входного файла и кнопку отправки. Динамически генерируемые идентификаторы / имена распознаются по префиксу j_id
.
- Подготовить
multipart/form-data
POST-запрос.
- Установите cookie-файл JSESSIONID (если не
null
) для этого запроса.
- Установите пару имя-значение для скрытого поля
javax.faces.ViewState
и кнопки.
- Установить файл для загрузки.
Вы можете использовать любую клиентскую библиотеку HTTP для выполнения задачи. Стандартный Java SE API предлагает java.net.URLConnection
для этого, что является довольно низким уровнем . Чтобы получить менее подробный код, вы можете использовать Apache HttpClient для выполнения HTTP-запросов и управления файлами cookie и Jsoup для извлечения данных из HTML.
Вот пример запуска, предполагая, что на странице есть только один <form>
(в противном случае вам необходимо включить уникальный идентификатор этой формы в селекторы CSS Jsoup):
String url = "http://localhost:8088/playground/test.xhtml";
String viewStateName = "javax.faces.ViewState";
String submitButtonValue = "Upload"; // Value of upload submit button.
HttpClient httpClient = new DefaultHttpClient();
HttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute(ClientContext.COOKIE_STORE, new BasicCookieStore());
HttpGet httpGet = new HttpGet(url);
HttpResponse getResponse = httpClient.execute(httpGet, httpContext);
Document document = Jsoup.parse(EntityUtils.toString(getResponse.getEntity()));
String viewStateValue = document.select("input[type=hidden][name=" + viewStateName + "]").val();
String uploadFieldName = document.select("input[type=file]").attr("name");
String submitButtonName = document.select("input[type=submit][value=" + submitButtonValue + "]").attr("name");
File file = new File("/path/to/file/you/want/to/upload.ext");
InputStream fileContent = new FileInputStream(file);
String fileContentType = "application/octet-stream"; // Or whatever specific.
String fileName = file.getName();
HttpPost httpPost = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
entity.addPart(uploadFieldName, new InputStreamBody(fileContent, fileContentType, fileName));
entity.addPart(viewStateName, new StringBody(viewStateValue));
entity.addPart(submitButtonName, new StringBody(submitButtonValue));
httpPost.setEntity(entity);
HttpResponse postResponse = httpClient.execute(httpPost, httpContext);
// ...