8 Replies Latest reply: Aug 7, 2012 4:04 PM by HDGeek RSS

    New BlobDomain from byte[] (retreived from database blob field)

      I am storing an uploaded file's content in a database blob field. As long as I do not leave the session when I first attach a file (using inputFile), then look at the file I have attached by clicking on a link that tells it to open, I can successfully open the file from the application by clicking on that link that has a child af:fileDownloadActionListener. The file successfully opens up in the appropriate application, like Word or Excel. If I close the session and reopen the application, hence pulling the blob data (which is the file content) from the database (vs. reading it from session as previously described), then I go to the link and click it, it tries to open the file, but it says the file is corrupted. I am creating an instance of a BlobDomain and using the blob retrieved from the database, which comes out of the database as a byte[], to instantiate that instance of the BlobDomain:

      private BlobDomain blobDomain;
      setBlobDomain(new BlobDomain(byte[] data)); //this is the byte[] the database provides when I fetch the record and get the blob field

      Then to open the file I retrieved from the database, I use the IOUtils:

      BlobDomain bd = new BlobDomain(getBlobDomain());

      // copy the data from the BlobDomain to the output stream
      IOUtils.copy(bd.getInputStream(), outputStream)

      // close the blob to release the recources
      // flush the output stream

      I notice when I do a system.out.println on what is in the BlobDomain variable, bd, it displays one thing when I look at it when it's running the code from session, and another thing when I'm running the code once I have fetched it from the database as the byte[].

      When I store the file in the database, I am creating the BlobDomain from the UploadedFile that is the datatype of the value retrieved from the inputFile component:
      private BlobDomain createBlobDomain(UploadedFile file){
      // init the internal variables
      InputStream in = null;
      BlobDomain blobDomain = null;
      OutputStream out = null;

      // Get the input stream representing the data from the client
      in = file.getInputStream();
      // create the BlobDomain datatype to store the data in the db
      blobDomain = new BlobDomain();
      // get the outputStream for hte BlobDomain
      out = blobDomain.getBinaryOutputStream();
      // copy the input stream into the output stream
      * IOUtils is a class from the Apache Commons IO Package (http://www.apache.org/)
      * Here version 2.0.1 is used
      * please download it directly from http://projects.apache.org/projects/commons_io.html
      IOUtils.copy(in, out);
      catch (IOException e)

      catch (SQLException e)


      // return the filled BlobDomain
      return blobDomain;

      Any suggestions why the file appears to be corrupted when trying to open it?


      Edited by: HDGeek on Aug 3, 2012 12:35 PM
        • 1. Re: New BlobDomain from byte[] (retreived from database blob field)
          Timo Hahn
          Why don't you use the blob domains stream and pipe it back to the client?
          When you get the data for the db it its a blob domain, so there is no need to get Byte[] and the build a BobDomain from it again.

          Check http://tompeez.wordpress.com/2011/12/16/jdev11-1-2-1-0-handling-imagesfiles-in-adf-part-3/ for a sample.

          • 2. Re: New BlobDomain from byte[] (retreived from database blob field)
            I am using EJB to persist the data, and it stores it as a byte[] data type. This is why I'm extracting it from the database as a byte[]. The solution you are suggesting is using ADFBC. In keeping with the EJB solution, is it possible to send the byte[] back to the ViewController and somehow convert it to a BlobDomain that can be used in IOUtils?
            • 3. Re: New BlobDomain from byte[] (retreived from database blob field)
              Timo Hahn
              For this you can use the IOUtils class which has a method http://commons.apache.org/io/apidocs/org/apache/commons/io/IOUtils.html#write(byte[], java.io.OutputStream) to write byte[] data to an outputstream.

              • 4. Re: New BlobDomain from byte[] (retreived from database blob field)
                I used IOUtils.write(byte[],outputstream) to no avail. The appropriate application opens (e.g. Excel), and it tries to load the file, but I am still getting a message that it cannot open the file and the file may be corrupted. I am now wondering if the problem is how it is being converted from the UploadFile type coming from the inputFile value to the byte[] I am storing in the database blob field as a byte[] (which is how the EBJ entity created the type (of byte[]) for the blob field when I created the entity bean from the table).

                Here is what I am doing in the valueChangeListener of the inputFile component to get from UploadFile to byte[]:
                UploadedFile uploadFile = (UploadedFile)e.getNewValue();
                strFile = parseISToString(uploadFile.getInputStream());
                setFileContents(strFile.getBytes()); //fileContents is a byte[] variable and this is what is being persisted to the database

                Here is my parseISToString method:
                public String parseISToString(java.io.InputStream is) {
                BufferedReader din = new BufferedReader(new InputStreamReader(is));
                StringBuffer sb = new StringBuffer();
                try {
                String line = null;
                int readLine = 0;
                while ((line = din.readLine()) != null || (readLine = din.read()) != -1) {
                sb.append(line + "\n");
                } catch (Exception ex) {
                } finally {
                try {
                } catch (Exception ex) {
                return sb.toString();

                Is is something in how I am building the string from the inputStream?

                • 5. Re: New BlobDomain from byte[] (retreived from database blob field)
                  I guess I had a similar kind of issue while uploading/downloading files. The file was corrupted when I used to download it. After debugging I found that the complete bytes(of file data) were not persisted properly into the database.
                  Can you try the following code to upload and download the files.(Though I am using ADFBC, you can ignore it and use EJB specific code if any)

                          public void uploadFile(ActionEvent actionEvent) {
                          UploadedFile file = (UploadedFile)uploadedFile.getValue();
                          if (file == null)
                          int counter = 0;
                          InputStream fileInpStr = null;
                          Map fileData = null;
                          Map sessionScope = ADFContext.getCurrent().getSessionScope();
                          if (file != null) {
                              int fileLength = (int)file.getLength();
                              byte[] b = new byte[fileLength];
                              String fileName = file.getFilename();
                              String contentType = file.getContentType();
                              DCBindingContainer bindings = ADFUtils.getDCBindingContainer();
                              ViewObject fileUploadVo =
                              Row r = fileUploadVo.createRow();
                              r.setAttribute("FetchedFromDB", "N");
                              r.setAttribute("FileName", fileName);
                              r.setAttribute("FileContentType", contentType);
                                             ADFUtils.getPageFlowScopeValue("description") !=
                                             null ?
                                             ADFUtils.getPageFlowScopeValue("description") :
                              seqNum = seqNum + 10;
                              r.setAttribute("SeqNumber", seqNum);
                              try {
                                  fileInpStr = file.getInputStream();
                                  byte[] bytes = new byte[(int)file.getLength()];
                                  int offset = 0, numRead = 0;
                                  while (offset < bytes.length &&
                                         ((numRead = fileInpStr.read(bytes, offset,
                                                                     bytes.length - offset)) >=
                                          0)) {
                                      offset += numRead;
                                  if (offset < bytes.length) {
                                      throw new IOException("Could not completely read file " +
                                  // Close the input stream and return bytes
                                  byte[] fileByteArray = null;
                                  String s = new String(Base64.encodeBase64(bytes));
                                  // Convert base64 string to a byte array
                                  fileByteArray = Base64.decodeBase64(s);
                                  //Put the byteArray in sessionScope. Key is combination of fileName and SeqNumber
                                  fileData.put(fileName + seqNum, fileByteArray);
                                  sessionScope.put("FileData", fileData);
                              } catch (Exception e) {
                              } finally {
                                  try {
                                  } catch (Exception e) {
                                      throw new JboException(e);
                              if (uploadedFile != null) {
                              ADFUtils.setPageFlowScopeValue("description", null);
                              if (description != null) {
                      public void downloadFileAction(FacesContext fctx, OutputStream out) {
                          //Code added
                          String fileContentType = null;
                          String fileName = null;
                          BlobDomain fileData = null;
                          Long fileId = null;
                          Map<String, Object> pageFlow =
                          if (pageFlow != null) {
                              fileId = (Long)pageFlow.get("reviewFileID");
                          if (fileId != null) {
                              DCBindingContainer bindings = ADFUtils.getDCBindingContainer();
                              ViewObjectImpl fileAttach =
                              RowQualifier qualf = new RowQualifier(" FileId = " + fileId);
                              Row[] rows = fileAttach.getFilteredRows(qualf);
                              if (rows.length == 1) {
                                  fileName = (String)rows[0].getAttribute("FileName");
                                  fileContentType =
                                  fileData = (BlobDomain)rows[0].getAttribute("FileData");
                          Long length = fileData.getLength();
                          //uagarwal Code added
                          HttpServletResponse response =
                                             "attachment;filename=\"" + fileName + "\"");
                          response.setContentType(fileContentType != null ? fileContentType :
                          try {
                              InputStream in = fileData.getBinaryStream();
                              byte[] buf = new byte[1024];
                              int count;
                              while ((count = in.read(buf)) >= 0) {
                                  out.write(buf, 0, count);
                          } catch (IOException ex) {
                  Hope it helps.
                  • 6. Re: New BlobDomain from byte[] (retreived from database blob field)
                    Timo Hahn
                    Well, the problem is that you are using string to load binary data. There are a couple of values which are handled different when you use string.
                    One easy way would be to use IOUtils to read the inputStream too. They handle the stream as binary and it should work OK.

                    A simple test if your data is stored in the DB is OK is to save the data using Data view from the db navigator. open the db and double click the table, then select the data tab and click on hte column holding the image data. In the dialog you should see the option to save the data to a file. Do so and try to open it in Excel or acrobat reader. If you can open it without an error, the data in the db is OK.

                    • 7. Re: New BlobDomain from byte[] (retreived from database blob field)
                      WOO HOO! That did the trick! I used this code:

                      byte[] buffer = IOUtils.toByteArray(uploadFile.getInputStream())

                      I saved the byte[] buffer to my blob database field, and when I retrieved it from the database, it opened in the appropriate application as I would expect it to!

                      Thanks so much for your help!!

                      Edited by: HDGeek on Aug 7, 2012 1:50 PM
                      • 8. Re: New BlobDomain from byte[] (retreived from database blob field)
                        Thanks for the awesome help and prompt feedback!