Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从JSF支持bean提供文件下载?_Jsf_Jsf 2_Download_Backing Beans - Fatal编程技术网

如何从JSF支持bean提供文件下载?

如何从JSF支持bean提供文件下载?,jsf,jsf-2,download,backing-beans,Jsf,Jsf 2,Download,Backing Beans,有没有办法从JSF支持bean操作方法提供文件下载? 我试过很多东西。主要问题是,我无法找到如何获取响应的OutputStream,以便将文件内容写入。我知道如何使用Servlet,但这不能从JSF表单调用,需要一个新的请求 如何从当前的FacesContext获取响应的OutputStream?简介 你可以把一切都搞定。在JSF1.x中,您可以通过以下方式获得原始HttpServletResponse对象。在JSF2.x中,您可以使用一系列新的委托方法,如,而无需从JSF框架下获取HttpSe

有没有办法从JSF支持bean操作方法提供文件下载? 我试过很多东西。主要问题是,我无法找到如何获取响应的
OutputStream
,以便将文件内容写入。我知道如何使用
Servlet
,但这不能从JSF表单调用,需要一个新的请求

如何从当前的
FacesContext
获取响应的
OutputStream

简介 你可以把一切都搞定。在JSF1.x中,您可以通过以下方式获得原始
HttpServletResponse
对象。在JSF2.x中,您可以使用一系列新的委托方法,如,而无需从JSF框架下获取
HttpServletResponse

在响应中,您应该设置
内容类型
标题,以便客户端知道要将哪个应用程序与提供的文件关联。而且,您应该设置
内容长度
标题,以便客户端可以计算下载进度,否则它将是未知的。而且,如果需要另存为对话框,则应将
内容处置
标题设置为
附件
,否则客户端将尝试以内联方式显示它。最后,只需将文件内容写入响应输出流

最重要的部分是调用通知JSF在将文件写入响应后不应执行导航和呈现,否则响应的结尾将被页面的HTML内容污染,或者在旧的JSF版本中,当JSF实现调用
getWriter()
来呈现HTML时,您将得到一个
IllegalStateException
,其中有一条消息,如已为此响应调用了
getoutputstream()

关闭ajax/不要使用远程命令! 您只需确保操作方法不是由ajax请求调用的,而是在使用
启动时由普通请求调用的。Ajax请求和远程命令由JavaScript处理,由于安全原因,JavaScript没有强制与Ajax响应内容进行另存为对话的功能

如果您正在使用PrimeFaces
,那么您需要确保通过
ajax=“false”
属性显式关闭ajax。如果您使用的是ICEfaces,则需要在命令组件中嵌套一个

通用JSF2.x示例 通用JSF1.x示例 通用静态文件示例 如果需要从本地磁盘文件系统流式传输静态文件,请按以下方式替换代码:

File file = new File("/path/to/file.ext");
String fileName = file.getName();
String contentType = ec.getMimeType(fileName); // JSF 1.x: ((ServletContext) ec.getContext()).getMimeType(fileName);
int contentLength = (int) file.length();

// ...

Files.copy(file.toPath(), output);
通用动态文件示例 如果您需要对动态生成的文件(如PDF或XLS)进行流式处理,则只需在此处提供
输出
,其中使用的API需要
输出流

例如,iText PDF:

String fileName = "dynamic.pdf";
String contentType = "application/pdf";

// ...

Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, output);
document.open();
// Build PDF content here.
document.close();
例如,Apache POI HSSF:

String fileName = "dynamic.xls";
String contentType = "application/vnd.ms-excel";

// ...

HSSFWorkbook workbook = new HSSFWorkbook();
// Build XLS content here.
workbook.write(output);
workbook.close();
请注意,您不能在此处设置内容长度。因此,您需要删除该行以设置响应内容长度。这在技术上没有问题,唯一的缺点是最终用户将收到未知的下载进度。如果这很重要,那么您确实需要首先写入本地(临时)文件,然后按照上一章所示提供它

实用方法 如果您使用的是JSF实用程序库,那么您可以使用三种方便的方法之一,即使用
文件
,或
输入流
,或
字节[]
,并指定该文件应作为附件(
true
)或内联(
false
)下载


是的,此代码按原样完整。您不需要自己调用
responseComplete()
等等。此方法还正确处理IE特定的头和UTF-8文件名。您可以找到。

这是完整的代码片段

@ManagedBean(name=“formBean”)
@会议范围
公共类FormBean实现了可序列化
{
私有静态最终长serialVersionUID=1L;
/**
*下载文件。
*/
public void downloadFile()引发IOException
{
File File=新文件(“C:\\docs\\instructions.txt”);
InputStream fis=新文件InputStream(文件);
字节[]buf=新字节[1024];
整数偏移=0;
int numRead=0;
而((偏移量=0))
{
偏移量+=numRead;
}
fis.close();
HttpServletResponse=
(HttpServletResponse)FacesContext.getCurrentInstance()
.getExternalContext().getResponse();
setContentType(“应用程序/八位字节流”);
setHeader(“内容处置”、“附件;文件名=instructions.txt”);
response.getOutputStream().write(buf);
response.getOutputStream().flush();
response.getOutputStream().close();
FacesContext.getCurrentInstance().responseComplete();
}
}

如果希望在运行时生成文件,您可以更改文件读取逻辑。

这对我来说很有用:

public void download() throws IOException
{

    File file = new File("file.txt");

    FacesContext facesContext = FacesContext.getCurrentInstance();

    HttpServletResponse response = 
            (HttpServletResponse) facesContext.getExternalContext().getResponse();

    response.reset();
    response.setHeader("Content-Type", "application/octet-stream");
    response.setHeader("Content-Disposition", "attachment;filename=file.txt");

    OutputStream responseOutputStream = response.getOutputStream();

    InputStream fileInputStream = new FileInputStream(file);

    byte[] bytesBuffer = new byte[2048];
    int bytesRead;
    while ((bytesRead = fileInputStream.read(bytesBuffer)) > 0) 
    {
        responseOutputStream.write(bytesBuffer, 0, bytesRead);
    }

    responseOutputStream.flush();

    fileInputStream.close();
    responseOutputStream.close();

    facesContext.responseComplete();

}
public void downloadFile(String filename) throws IOException {
    final FacesContext fc = FacesContext.getCurrentInstance();
    final ExternalContext externalContext = fc.getExternalContext();

    final File file = new File(filename);

    externalContext.responseReset();
    externalContext.setResponseContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType());
    externalContext.setResponseContentLength(Long.valueOf(file.lastModified()).intValue());
    externalContext.setResponseHeader("Content-Disposition", "attachment;filename=" + file.getName());

    final HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

    FileInputStream input = new FileInputStream(file);
    byte[] buffer = new byte[1024];
    final ServletOutputStream out = response.getOutputStream();

    while ((input.read(buffer)) != -1) {
        out.write(buffer);
    }

    out.flush();
    fc.responseComplete();
}

很容易!我一直想知道如何根据PrimeFaces的showcase为其提供下载,因为它需要
InputStream
基础结构才能下载
p:fileDownload
,而我还没有设法将
OutputStream
转换为
InputStream
。现在很明显,即使是操作侦听器也可以更改响应内容类型,然后响应将在用户代理端作为文件下载。非常感谢。有没有办法使用HTTP GET而不是HTTP POST(h:commandButton和h:commandLink)?@Alfredo:有,在无标记视图中使用
preRenderView
侦听器。这里回答了下载(好吧,服务)JSON的类似问题:链接断开了。也许这一个是合适的:@BalusC你涵盖了每一个jsf主题-谢谢你的支持
public void download() throws IOException {
    Faces.sendFile(file, true);
}
 @ManagedBean(name = "formBean")
 @SessionScoped
 public class FormBean implements Serializable
 {
   private static final long serialVersionUID = 1L;

   /**
    * Download file.
    */
   public void downloadFile() throws IOException
   {
      File file = new File("C:\\docs\\instructions.txt");
      InputStream fis = new FileInputStream(file);
      byte[] buf = new byte[1024];
      int offset = 0;
      int numRead = 0;
      while ((offset < buf.length) && ((numRead = fis.read(buf, offset, buf.length -offset)) >= 0)) 
      {
        offset += numRead;
      }
      fis.close();
      HttpServletResponse response =
         (HttpServletResponse) FacesContext.getCurrentInstance()
        .getExternalContext().getResponse();

     response.setContentType("application/octet-stream");
     response.setHeader("Content-Disposition", "attachment;filename=instructions.txt");
     response.getOutputStream().write(buf);
     response.getOutputStream().flush();
     response.getOutputStream().close();
     FacesContext.getCurrentInstance().responseComplete();
   }
 }
public void download() throws IOException
{

    File file = new File("file.txt");

    FacesContext facesContext = FacesContext.getCurrentInstance();

    HttpServletResponse response = 
            (HttpServletResponse) facesContext.getExternalContext().getResponse();

    response.reset();
    response.setHeader("Content-Type", "application/octet-stream");
    response.setHeader("Content-Disposition", "attachment;filename=file.txt");

    OutputStream responseOutputStream = response.getOutputStream();

    InputStream fileInputStream = new FileInputStream(file);

    byte[] bytesBuffer = new byte[2048];
    int bytesRead;
    while ((bytesRead = fileInputStream.read(bytesBuffer)) > 0) 
    {
        responseOutputStream.write(bytesBuffer, 0, bytesRead);
    }

    responseOutputStream.flush();

    fileInputStream.close();
    responseOutputStream.close();

    facesContext.responseComplete();

}
public void downloadFile(String filename) throws IOException {
    final FacesContext fc = FacesContext.getCurrentInstance();
    final ExternalContext externalContext = fc.getExternalContext();

    final File file = new File(filename);

    externalContext.responseReset();
    externalContext.setResponseContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType());
    externalContext.setResponseContentLength(Long.valueOf(file.lastModified()).intValue());
    externalContext.setResponseHeader("Content-Disposition", "attachment;filename=" + file.getName());

    final HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

    FileInputStream input = new FileInputStream(file);
    byte[] buffer = new byte[1024];
    final ServletOutputStream out = response.getOutputStream();

    while ((input.read(buffer)) != -1) {
        out.write(buffer);
    }

    out.flush();
    fc.responseComplete();
}