Artem P.
Artem P.

Reputation: 105

Download file after ItemNode click

I use oracle-adf via xml menu model. Now I want to start download file on one of itemNode and without redirect. I'm tried to define action attribute with method which invokes hidden button's method(this button has inner fileDownloadActionListener) through javascript. But it doesn't work. Is it correct? or there is other way to decide this problem? Or may be it is impossible at all?

Hidden button code:

<af:commandButton text="NONE"
                    id="downloadInstructionsBtn"
                    action=" "
                    visible="false"
                    clientComponent="true"
                    partialSubmit="false">
       <af:fileDownloadActionListener filename="Инструкции пользователя"
       contentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                                     method="#{pageFlowScope.vocsReportsRegionController.instructionsDownload}"/> 
</af:commandButton>

Item node code:

<itemNode id="userInstructionsDownloadFlow" label="Инструкции пользователя"
              focusViewId="#"
              action="#{pageFlowScope.vocsReportsRegionController.invokeInstructionDownload}"
              partialSubmit="true"
              clientComponent="true"/>

Javascript cut:

function handleInstructionsDownload(event) {
    event.preventUserInput();
    var source = event.getSource().getParent();
    var downloadBtn = source.findComponent("downloadInstructionsBtn");
    var actionEvent = new AdfActionEvent(downloadBtn);
    actionEvent.preventUserInput();
    actionEvent.queue();
}

Methods' description:

public void invokeInstructionDownload(){
    FacesContext context = FacesContext.getCurrentInstance();
    ExtendedRenderKitService erks =
            Service.getService(context.getRenderKit(),
                    ExtendedRenderKitService.class);

    erks.addScript(context, "handleInstructionsDownload();");
}

public void instructionsDownload(FacesContext context,
                                 OutputStream out) throws IOException{
    File f = new File("C:\\Users\\apozdnyakov\\Downloads\\Типы_контроля_время.xlsx");
    FileInputStream fis;
    byte[] b;
    try {
        fis = new FileInputStream(f);

        int n;
        while ((n = fis.available()) > 0) {
            b = new byte[n];
            int result = fis.read(b);
            out.write(b, 0, b.length);
            if (result == -1)
                break;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    out.flush();
}

Upvotes: 0

Views: 467

Answers (1)

adilkun
adilkun

Reputation: 41

I think there are a few possible reasons of your problem.

1- handleInstructionsDownload javascript function couldn't find the component, because of hierarchy of the jsf codes. You can add log in javascript function, for understanding that.

function handleInstructionsDownload(event) {
  event.preventUserInput();
  var source = event.getSource().getParent();
  var downloadBtn = source.findComponent("downloadInstructionsBtn");
  if (downloadBtn == null) {
    console.log('The component is null!');
  }
  var actionEvent = new AdfActionEvent(downloadBtn);
  actionEvent.preventUserInput();
  actionEvent.queue();
}

If you see this log in javascript console you should control your hierarchy of jsf codes. And you should access to button by true component id.

2- invokeInstructionDownload java method couldn't find or call the javascript handleInstructionsDownload function. You can add log in the first line of the javascript function like that:

function handleInstructionsDownload(event) {
  console.log('The js function fired!');
  event.preventUserInput();
  var source = event.getSource().getParent();
  var downloadBtn = source.findComponent("downloadInstructionsBtn");
  var actionEvent = new AdfActionEvent(downloadBtn);
  actionEvent.preventUserInput();
  actionEvent.queue();
}

If there is this log in console, you should change your javascript method calling. But I think your Java method is true :)

3- If these are not solutions of your problem, you can change your calling the hidden button like that.

Hidden button code:

<af:commandButton text="NONE" 
                  id="downloadInstructionsBtn" action=" "
                  visible="false"
                  clientComponent="true"
                  partialSubmit="false"
                  binding="#{pageFlowScope.vocsReportsRegionController.downloadInstructionsBtn}">
   <af:fileDownloadActionListener filename="Инструкции пользователя"
                  contentType="application/vnd.openxmlformats officedocument.spreadsheetml.sheet"
                  method="#{pageFlowScope.vocsReportsRegionController.instructionsDownload}"/> 
</af:commandButton>

ManagedBean code:

private RichButton downloadInstructionsBtn;

public RichButton getDownloadInstructionsBtn() {
  return downloadInstructionsBtn;
}

public void setDownloadInstructionsBtn(RichButton downloadInstructionsBtn) {
  this.downloadInstructionsBtn = downloadInstructionsBtn;
}

public void invokeInstructionDownload(){
  ActionEvent actionEvent = new ActionEvent((UIComponent) downloadInstructionsBtn);
  actionEvent.queue();
}

Upvotes: 0

Related Questions