Показать / скачать TXT или CSV-файл с помощью команды LinkLink и Tree2 Томагавк JSF
У меня есть дерево (tree2 tomahawk 1.1.11), которое показывает список каталогов и файлов. Когда я нажимаю на файл, я хотел бы показать диалоговое окно загрузки, чтобы позволить клиенту загрузить файл. Моя страница выглядит так
...
<h:form>
<t:tree2 id="tree" value="#{listFiles.treeData}"
var="node" varNodeToggler="t" >
<f:facet name="folder">
<h:panelGroup>
<f:facet name="expand">
<t:graphicImage value="images/folderOpen.png"
rendered="#{t.nodeExpanded}}"
border="0" />
</f:facet>
<f:facet name="collapse">
<t:graphicImage value="images/folderClose.png"
rendere="#{t.nodeExpanded}}"
border="0" />
</f:facet>
<h:outputText value="#{node.description}"
styleClass="nodeFolder" />
</h:panelGroup>
</f:facet>
<f:facet name="file">
<h:panelGroup>
<h:commandLink action="#{listFiles.download()}" >
<t:graphicImage value="images/file.png" border="0" />
<h:outputText value="#{node.description}" />
</h:commandLink>
</h:panelGroup>
</f:facet>
</t:tree2>
</h:form>
...
И мой боб
@ManagedBean
@RequestScoped
public class ListFiles implements Serializable {
private String path = "C:\\";
private TreeNode treeRoot;
private File dirRoot;
@ManagedProperty("#{userVerifier}")
private UserVerifier userVerifier;
public void setUserVerifier(UserVerifier userVerifier) {
this.userVerifier = userVerifier;
}
public UserVerifier getUserVerifier() {
return userVerifier;
}
public TreeNode getTreeData() {
path = loadConfiguredPath();
String dependencia = userVerifier.getDependencia();
if (dependencia.equals("DESARROLLO")) {
path = path + "dataFiles";
treeRoot = new TreeNodeBase("folder", "SRC", false);
} else {
path = path + "dataFiles\\" + dependencia;
treeRoot = new TreeNodeBase("folder", dependencia, false);
}
dirRoot = new File(path);
createTree(dirRoot, treeRoot);
return treeRoot;
}
private void createTree(File fileRoot, TreeNode treeRoot) {
File[] files = fileRoot.listFiles();
TreeNodeBase tnb;
for (File f : files) {
if (f.isDirectory()) {
tnb = new TreeNodeBase("folder", f.getName(), false);
treeRoot.getChildren().add(tnb);
createTree(f, tnb);
}
if (f.isFile()) {
tnb = new TreeNodeBase("file", f.getName(), false);
treeRoot.getChildren().add(tnb);
}
}
return;
}
private String loadConfiguredPath() {
String dir;
ReadXML reader = new ReadXML(".\\webapps\\SRC\\configFiles\\confSRC.xml");
dir = reader.getValue("baseDir");
if (dir == null) {
return path;
} else {
return dir;
}
}
public String download(){
System.out.println("Yes we are downloading");
return "ok";
}
}
Все работает отлично, за исключением того, что я не знаю, как выполнить загрузку при нажатии на h: commandLink
Единственный тип файлов, которые у меня есть, это txt или csv.
ОБНОВИТЬ:
Теперь, когда у меня есть код, это исключение выдается.
javax.servlet.ServletException
javax.faces.webapp.FacesServlet.service(FacesServlet.java:422)
org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:349)
ОБНОВИТЬ:
Я выложу свой web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<filter>
<filter-name>MyFacesExtensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
<init-param>
<param-name>uploadMaxFileSize</param-name>
<param-value>5g</param-value>
</init-param>
<init-param>
<param-name>uploadThresholdSize</param-name>
<param-value>500m</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFacesExtensionsFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>MyFacesExtensionsFilter</filter-name>
<servlet-name>/faces/*</servlet-name>
</filter-mapping>
<context-param>
<param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>
<param-value>false</param-value>
</context-param>
</web-app>
1 ответ
По сути, вам нужно пройти физическое File
или по крайней мере File#getAbsolutePath()
в качестве значения, чтобы метод действия загрузки мог прочитать его с диска. Я никогда не использовал <t:tree2>
поэтому я проверил Javadoc TreeNodeBase
и это, кажется, не поддерживает ничего, кроме String description
в качестве значения узла. Невозможно установить его с File
, Так что вам действительно нужно пройти File#getAbsolutePath()
вниз в это. Я думаю, что вы можете использовать String identifier
аргумент для этого:
tnb = new TreeNodeBase("file", f.getName(), f.getAbsolutePath(), false);
Затем, в представлении, просто передайте его методу действия:
<h:commandLink action="#{listFiles.download(node.identifier)}" >
Наконец, передайте это следующим образом:
public String download(String absolutePath) throws IOException {
File file = new File(absolutePath);
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.setResponseHeader("Content-Type", externalContext.getMimeType(file.getName()));
externalContext.setResponseHeader("Content-Length", String.valueOf(file.length()));
externalContext.setResponseHeader("Content-Disposition", "attachment;filename=\"" + file.getName() + "\"");
InputStream input = null;
OutputStream output = null;;
try {
input = new FileInputStream(file);
output = externalContext.getResponseOutputStream();
IOUtils.copy(input, output);
} finally {
IOUtils.closeQuietly(output);
IOUtils.closeQuietly(input);
}
facesContext.responseComplete();
}