Загрузите файл с помощью JSF?
который является правильным способом загрузки файла с помощью JSF?, просто поместив ссылку на файл? в этом случае, как получить URL-адрес файла?
Я видел один пример с использованием BufferedInputStream:
http://www.winstonprakash.com/articles/jsf/file_download_link.htm
В чем отличия?
Спасибо
Ответы
Ответ 1
Если это простой файл, просто разместите его в общедоступном webcontent (там, где вы ставите свои статические и JSF файлы) и создаете ссылку.
<h:outputLink value="/files/file.ext">link</h:outputLink>
Сервлетконтейнер будет беспокоиться о применении правильных заголовков.
Если он находится за пределами общедоступного webcontent по некоторым конкретным причинам (например, по фиксированному пути на серверной машине или в базе данных), тогда создайте сервлет, который получает InputStream
и записывает его в OutputStream
ответа по крайней мере на Content-Type
, Content-Disposition
и Content-Length
. Вы можете найти здесь простой пример запуска. Также это можно просто связать с сервлетами url-pattern
.
Если он будет динамически генерироваться и зависит от специфических параметров запроса JSF, вы также можете сделать это в управляемом действии bean, которое связано с h:commandLink
или h:commandButton
, но вам нужно только убедиться, что вы вызываете FacesContext#responseComplete()
в конце метода действия bean, чтобы предотвратить JSF от навигации в руках. Такой же код сервлета можно повторно использовать для потоковой передачи файла. Вы можете найти пример запуска в этом ответе.
Ответ 2
Мне нужно было сделать аналогичный код для загрузки файла через JSF
Что моя кнопка загрузки на моей странице JSF
<h:commandButton value="Download" action="#{helloBean.downloadFile}" />
И это мой код Java
public void downloadFile() {
File file = new File("/home/marco/file.txt");
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.setHeader("Content-Disposition", "attachment;filename=file.txt");
response.setContentLength((int) file.length());
ServletOutputStream out = null;
try {
FileInputStream input = new FileInputStream(file);
byte[] buffer = new byte[1024];
out = response.getOutputStream();
int i = 0;
while ((i = input.read(buffer)) != -1) {
out.write(buffer);
out.flush();
}
FacesContext.getCurrentInstance().getResponseComplete();
} catch (IOException err) {
err.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException err) {
err.printStackTrace();
}
}
}
Ответ 3
У меня была ошибка на
FacesContext.getCurrentInstance().getResponseComplete();
от типа
java.lang.IllegalStateException: getOutputStream() has already been called for this response
и я решил:
Страница JSF:
<h:commandButton action="#{bean.downloadFile}" id="downloadBtn" value="Download"/>
Bean метод:
public void downloadFile(File file) {
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.setHeader("Content-Disposition", "attachment;filename=file.txt");
response.setContentLength((int) file.length());
FileInputStream input= null;
try {
int i= 0;
input = new FileInputStream(file);
byte[] buffer = new byte[1024];
while ((i = input.read(buffer)) != -1) {
response.getOutputStream().write(buffer);
response.getOutputStream().flush();
}
facesContext.responseComplete();
facesContext.renderResponse();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(input != null) {
input.close();
}
} catch(IOException e) {
e.printStackTrace();
}
}
}