Sunday, 23 December 2012

ADF Single/Multiple files uploading and downloading

This post is about to upload single file/multiple files from the client to the server and store the data in a BLOB column in Database.

First of all, we have to create a table to store files in database:

CREATE TABLE "HR"."DOCUMENTS"
  (
    "DOCUMENT_ID"   NUMBER NOT NULL ENABLE,
    "DOCUMENT_NAME" VARCHAR2(50 BYTE),
    "DOCUMENT_TYPE" VARCHAR2(100 BYTE),
    "DOCUMENT_FILE" BLOB,
    CONSTRAINT "DOCUMENTS_PK" PRIMARY KEY ("DOCUMENT_ID") 

  )

Single file upload 

Below is the UI for single file upload  with a table with uploaded files along with the download button for each file.


 Steps to achieve single file uploading:

1. Add inputFile component on jspx page:

  <af:inputFile label="Upload File" id="if1"
       binding="#{pageFlowScope.SingleFileUploadDownloadBean.inputFile}"
       valueChangeListener="#{pageFlowScope.SingleFileUploadDownloadBean.onFileUploadVCL}"
        autoSubmit="true"/>

  
  Add a button to trigger the action to upload the File:

 <af:commandButton text="Upload" id="cb1"
          disabled="#{pageFlowScope.SingleFileUploadDownloadBean.inputFile.value == null ? true : false}"
          partialTriggers="if1"
          actionListener="#{pageFlowScope.SingleFileUploadDownloadBean.onFileUpload}"
          partialSubmit="true"/>


2. Drag and drop the DocumentsVO on page as Adf Table. Remove the Blob column from the table and add a new column in UI to enable File downloading:

//Comment out or remove Blob Column from the table
<!--<af:column sortProperty="DocumentFile" sortable="false"
                             headerText="#{bindings.DocumentsVO1.hints.DocumentFile.label}"
                             id="c1">
                    <af:inputText value="#{row.bindings.DocumentFile.inputValue}"
                                  label="#{bindings.DocumentsVO1.hints.DocumentFile.label}"
                                  required="#{bindings.DocumentsVO1.hints.DocumentFile.mandatory}"
                                  columns="#{bindings.DocumentsVO1.hints.DocumentFile.displayWidth}"
                                  maximumLength="#{bindings.DocumentsVO1.hints.DocumentFile.precision}"
                                  shortDesc="#{bindings.DocumentsVO1.hints.DocumentFile.tooltip}"
                                  id="it1">
                      <f:validator binding="#{row.bindings.DocumentFile.validator}"/>
                    </af:inputText>
  </af:column>-->

//Add new Column to add Download button in each row
 <af:column id="c1" width="413"
                                     headerText="File Download">
                            <af:commandButton text="Download File" id="cb3">
                              <af:fileDownloadActionListener contentType="#{row.bindings.DocumentType.inputValue}"
                                                             filename="#{row.bindings.DocumentName.inputValue}"
                                                             method="#{pageFlowScope.SingleFileUploadDownloadBean.downloadFile}"/>
                            </af:commandButton>
 </af:column>


3. In ManagedBean : (Here bean name is SingleFileUploadDownloadBean)

    private RichInputFile inputFile;
    private String fileName;
    private String contentType;
    private UploadedFile file;
    private BlobDomain blob;

 // Value Change Listener for inputFileComponent
    public void onFileUploadVCL(ValueChangeEvent valueChangeEvent) {
        file = (UploadedFile)valueChangeEvent.getNewValue();
        // Get the file name
        fileName = file.getFilename();
        // get the mime type
        contentType = file.getContentType();
        // get blob
        blob=getBlob(file);     
    }

 // Method to get Blob
    public BlobDomain getBlob(UploadedFile file){      
            InputStream in = null;
            BlobDomain blobDomain = null;
            OutputStream out = null;
            try
            {               
                in = file.getInputStream();             
                blobDomain = new BlobDomain();              
                out = blobDomain.getBinaryOutputStream();               
                IOUtils.copy(in, out);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            catch (SQLException e)
            {
                e.fillInStackTrace();
            }          
            return blobDomain;
    }

//Method to invoke Operation binding to upload file in database
    public void onFileUpload(ActionEvent actionEvent) {      
        DCBindingContainer bc = ADFUtil.getBindingContainer();
        OperationBinding operationbinding = bc.getOperationBinding("uploadFiletoDB");
        if(operationbinding!=null){
            operationbinding.getParamsMap().put("fileName", fileName);
            operationbinding.getParamsMap().put("contentType", contentType);
            operationbinding.getParamsMap().put("blob", blob);
            operationbinding.execute();
        }
        System.out.println("File uploaded successfully");
        if (inputFile != null) {
            inputFile.resetValue();
            inputFile.setValid(true);
        }
    }

//Method to download File
Note: Make sure that Row Selection must be single and in SelectionListener should be present in ADF table on jspx page:

    public void downloadFile(FacesContext facesContext,
                             OutputStream outputStream) {
        DCBindingContainer bindings = ADFUtil.getBindingContainer();
        DCIteratorBinding iteratorbinding =
            bindings.findIteratorBinding("DocumentsVO1Iterator");
        BlobDomain blob =
            (BlobDomain)iteratorbinding.getCurrentRow().getAttribute("DocumentFile");
        try {
            IOUtils.copy(blob.getInputStream(), outputStream);
            blob.closeInputStream();
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


Multiple files upload :

Here we can add multiple inputFile component on click of Add Attachment button and remove the same by clicking Remove Attachment button. By default one inputFile component will be displayed. And after uploading single/multiple files, on click of Upload Files button, the uploaded files will be stored in database.


  Steps to achieve multiple files uploading:

 1. We will use forEach to add multiple inputFile component

<af:forEach items="#{pageFlowScope.MultipleFileUploadDownloadBean.rowFields}" var="row">
   <af:inputFile label="Upload File" id="if2"
    binding="#{pageFlowScope.MultipleFileUploadDownloadBean.map['FIELD'].inputFile}"
    autoSubmit="true"
     valueChangeListener="#{pageFlowScope.MultipleFileUploadDownloadBean.onFileUploadVCL}"
     partialTriggers="cb5"/>            
  </af:forEach>


//Add attachment Button to create new inputFile at runtime 
 <af:commandButton text="Add Attachment" id="cb4"
    actionListener="#{pageFlowScope.MultipleFileUploadDownloadBean.onAddFile}"/>


 2. We will create a separate class to create Multiple inputFile component:

import oracle.adf.view.rich.component.rich.input.RichInputFile;

public class FileUpload {
    private RichInputFile inputFile;
    public FileUpload() {
        super();
    }

    public void setInputFile(RichInputFile inputFile) {
        this.inputFile = inputFile;
    }

    public RichInputFile getInputFile() {
        return inputFile;
    }
}
 

3. In ManagedBean:

    private List fileNameList = new ArrayList();
    private List fileContentTypeList = new ArrayList();
    private List fileBlobList = new ArrayList();
    private List fileSizeList = new ArrayList();
    private List<HashMap> fieldlist = new ArrayList<HashMap>();
    private HashMap<String, FileUpload> map;

    private int fileCounter = 0; 

//In constructor add below code to add single inputFile component on first time page load
    public MultipleFileUploadDownloadBean() {
        map = new HashMap<String, FileUpload>();
        try {
            FileUpload test = new FileUpload();
            map.put("FIELD", test);
            fieldlist.add(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } 


// Method to create new InputFile on UI
    public void onAddFile(ActionEvent actionEvent) {
        map = new HashMap<String, FileUpload>();
        try {
            FileUpload inputFile = new FileUpload();
            map.put("FIELD", inputFile);
            fieldlist.add(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } 


//Method to remove inputFile on UI 
    public void onRemoveFile(ActionEvent actionEvent) {
        if (fieldlist.size() > 1) {
            fieldlist.remove(fieldlist.size() - 1);
        }
    }

 


 //Value Change Listener for inputFile
     public void onFileUploadVCL(ValueChangeEvent valueChangeEvent) {
        UploadedFile file;
        file = (UploadedFile)valueChangeEvent.getNewValue();
        fileNameList.add(file.getFilename());
        fileContentTypeList.add(file.getContentType());
        fileSizeList.add(file.getLength());
        fileBlobList.add(getBlob(file));

        // file counter to limit no of files that can be uploaded
        fileCounter++;
    }

  
// Method to invoke Operation binding to upload multiple files in database
    public void onFileUpload(ActionEvent actionEvent) {
        DCBindingContainer bc = ADFUtil.getBindingContainer();
        OperationBinding operationbinding =
            bc.getOperationBinding("uploadMultipleFilestoDB");
        if (operationbinding != null) {
            operationbinding.getParamsMap().put("fileNameList", fileNameList);
            operationbinding.getParamsMap().put("fileContentTypeList",
                                                fileContentTypeList);
            operationbinding.getParamsMap().put("fileBlobList", fileBlobList);
            operationbinding.execute();
        }
        System.out.println("File uploaded successfully");
    }



 Find the sample app here


58 comments:

  1. Hi Bharat,

    Thank you for this great article! I've just noticed a small issue when I ran your Sample application. "Attribute DocumentId in AppModule.DocumentsVO1 is required." Is there something missing ?

    Thank you again

    ReplyDelete
    Replies
    1. Jerome,
      Try this out:

      Run the below script:
      create sequence "HR"."DOCUMENTS_S" minvalue 1 maxvalue 999999
      INCREMENT BY 1 START WITH 1;

      In DepartmentEO.xml
      Edit the entity attribute: DepartmentId
      Select ValueType as Expression and provide the below value:
      (new oracle.jbo.server.SequenceImpl('DOCUMENTS_S',object.getDBTransaction())).getSequenceNumber()

      Now run the home.jspx

      Delete
  2. Thanks a lot...
    Nice job :)

    ReplyDelete
  3. Hi Bharat,

    Is it possible to use af:inputFile inside the table?

    ReplyDelete
    Replies
    1. Hi Aaron,

      Yes we can use af:inputFile inside ADF table.

      Thanks

      Delete
  4. Hi,

    Nice post.but when i run the page it wont saved.so how can i save the uploaded file in some place.my requirement is when one user get login and used to upload a file,it would be saved and when the same user login the page,the old uploaded files would be appeared.so how can i reach this scenario.pls help me out.

    Thanks,
    G.Shilpa

    ReplyDelete
    Replies
    1. HI Shilpa,

      You can use DB table to save uploaded file content in BLOB data type. Use the sample app I attached with above post and let me know if you face any issue.

      Regards,
      Bharat

      Delete
  5. thank you very much,i need the application you did,My Email: wanganleichina@gmail.com
    Thanks again.

    ReplyDelete
  6. hi bharat,
    thanks for the sourcecode. But how to increase speed of upload when we upload files exceed size of 20MB

    ReplyDelete
  7. Hi Bharath,
    Can u please provide me ADFutil also or please guid me where i can find it

    ReplyDelete
    Replies
    1. Download ADFUtil from below location:

      https://bbhaskar.opendrive.com/files?Ml80MjE1OTY3OF9IaUhhYw

      Delete
  8. This comment has been removed by the author.

    ReplyDelete
  9. hi Bharat,
    the Sample app link is broken, could you restore it?

    ReplyDelete
  10. or send it to my email id,My Email: vicbri@gmail.com

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. hi bharat
    i have try do this application in the same way as u did but i am getting an error in this line of code,can tell me y this error is occuringm i am getting error in Blobdomain getblob(UploadedFile file)

    IOUtils.copy(in, out);
    it is showing error as method not found

    ReplyDelete
    Replies
    1. you need the Commons IO package in the version 2.0.1 you can download from the Apache Software Foundation apache web side

      Delete
    2. I have download the file and added to the librery through the jdev but even then it is showing red line under that statement..is there anything that I must do after adding the .jar file to the ilbrary,could u please help me what to after adding the file..there 2 files binary nad source which one to download.

      Delete
  13. hi bharat can u send the application to my email kintali.kiran1989@gmail.com

    ReplyDelete
  14. Hi

    I did the same what you said. But when I run the app it showing "File loaded successfully". But i cant see it in table. I am getting "No data to display".
    Please help me.

    Thanks in advance

    ReplyDelete
  15. This comment has been removed by the author.

    ReplyDelete
  16. hi bharat can u send the application to my email
    mehanashameed@gmail.com

    ReplyDelete
  17. hi bharat can you send your app to my email: lovetkh@yahoo.com.
    Thanks a lot.

    ReplyDelete
  18. Hi Bharat Bhaskar,

    I did the same what you said. But when I run the app it showing "File loaded successfully". But i cant see it in table. I am getting "No data to display". and can you please send this application on nasiramin43@gmail.com ? Please!


    Thanks in advance

    ReplyDelete
  19. hi bharat can you send your app to my email:caybachduong13@gmail.com.
    Thanks a lot.

    ReplyDelete
  20. hi,
    can you please send this code on my mail id hopes.nitin@gmail.com

    Thanks in advance :)

    ReplyDelete
  21. Hi Bharat Bhaskar,

    Can you send your code to my email: wmurillodf@gmail.com

    Thanks a lot!

    ReplyDelete
  22. Hi Bharat,

    Would you be able to provide a download link to the sample app please? The current link is broken.

    Thanks!

    ReplyDelete
  23. Hi,
    its not possible download your example, you can send me the proiect

    ReplyDelete
  24. Hi,
    its not possible download your example, you can send me the proiect (whuera@gmail.com)

    ReplyDelete
  25. Hi,

    This is exactly what I was looking for but I could not download the example code. Can you please send the application to me (david.beck[at]gmail.com)? Thank you.

    ReplyDelete
  26. Hi,

    Could you please send this samples for me. Thanks le171282[at]gmail.com

    ReplyDelete
  27. Thanks for your work.

    Could you send me yours jdev project adfkho@gmail.com

    KM

    ReplyDelete
  28. Hi bharat can you send your app to my email: msalimdayer@gmail.com
    Thanks

    ReplyDelete
  29. This comment has been removed by the author.

    ReplyDelete
  30. Hi Bharat
    Could you please send your app to sundaram.babu01@gmail.com

    ReplyDelete
  31. Hi Bharat,
    Can you send me too the app please on max.makarovsky@gmail.com
    Thank You

    ReplyDelete
  32. hi bharat can u send the application to my email n.n.sarma@gmail.com

    ReplyDelete
  33. Hello,

    Thank you very much for the post, but the download link is broken.

    Can you please send the app to shokeros@hotmail.co.uk ?

    Kind regards
    Onkar

    ReplyDelete
  34. Hi Bharat,

    Can you please share the app with me. My Id is firdausayed@gmail.com

    Thank you.

    ReplyDelete
  35. Hi Bharat,

    Can you please share the app with me. My Id is ah.attieh@gmail.com

    Thank you

    ReplyDelete
  36. Hi Bharat,
    Could you please send me the app on ibrahimrefaat@gmail.com
    Thanks so much.

    ReplyDelete
  37. Hi Bharat,
    Could you please send me the app on sandip.wavhal@gmail.com
    Thanks so much.

    ReplyDelete
  38. Hi Bharat,
    Could You please send the application in my mail 24info.amar@gmail.com since the link which you have mentioned is broken.
    Thanks a lot

    ReplyDelete
  39. Hi Bharat,

    Could you please share the sample app as the link is broken.Thanks in advance.

    Regards,
    Abhijit

    ReplyDelete
  40. Hi Bharat,

    I'm try to make this app working since a couple of days but can't get it...
    I have problems with the binding that always return null so it didn't upload to the DB.
    It is possible to share the sample app again ?

    Best regards,
    Stefan

    ReplyDelete
  41. Hi Bharat,
    I am try to upload a file using the same code, but the data does not enter to the DB.There is no error and the message 'The file upload successfully' is printed. The 'operationbinding' variable return a null value. Please send this app to my mail 'kmgreeshma8@gmail.com'.
    Regards,
    Greeshma K M

    ReplyDelete
  42. Hi Bharat,

    I am implemented single file upload and download in my application, but my requirement is upload same file again with version.

    ReplyDelete
  43. Dear Bharat
    this link its not working can you send me sample on younies123@hotmail.com

    appreciate your help

    ReplyDelete
  44. HI bharat,
    iam trying to open the sample app but i cannot downalod the file.please i request you to send to my mail or if any one has the file pls forward to A.shiva77@gmail.com

    ReplyDelete
  45. Could you please send me the app on abid_med_ali@yahoo.fr

    ReplyDelete
  46. Hi Bharat,
    Could you please send me the app on najibnugroho@outlook.com
    Thanks so much

    ReplyDelete
  47. Hi Bharat,
    Could You please send the application in my mail 24443450@qq.com since the link which you have mentioned is broken.
    Thanks a lot

    ReplyDelete
  48. how to show the error at frontend if no file present in managedBean .
    or any IO error occurred then how to show customized error in screen.

    ReplyDelete