lundi 15 octobre 2012

Opening streamed file with flex, without saving it


When we send streamed files from the backend to the flex frontend, we have at least two ways to 'read' it.

The first common way is to save it using a FilReference.But this way need a confirmation flex popup, and sometimes the flex application is too goodlooking that you're disgusted when the archaic 'Save As' window is displayed!! Espacially when we don't really need to save the file and only want to have a fast look into the document before may be saving it.

It's why there are a second way to handle this, at least for PDF and XLS documents. (and may be for other file types but you have to google it). The way is to open the streamed document into an other tab using a java servlet, and let the web browser decide wich software would open it.

Here is a code sample for PDF :
public static function exportPdfFromStream(stream:ByteArray,
                                           fileName:String):void {
    var header:URLRequestHeader =
        new URLRequestHeader ("Content-type","application/octet-stream");
    var myRequest:URLRequest =
        new URLRequest (urlApplication+ 'CreatePDF' +
                       '?name='+fileName+'&method=attachment');
    myRequest.requestHeaders.push (header);
    myRequest.method = URLRequestMethod.POST;
    myRequest.data = stream;
    navigateToURL(myRequest,"_blank");
}

For Csv you just need to change the header content-type :
var header:URLRequestHeader =
    new URLRequestHeader("Content-type", "application/vnd.ms-excel");

Here is the way to declare the java servlet :
<servlet>
      <servlet-name>createPDF</servlet-name>
      <servlet-class>
          com.manpower.socle.tools.CreatePDFServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
      <servlet-name>createPDF</servlet-name>
      <url-pattern>/client/createPDF</url-pattern>
</servlet-mapping>



And this is the servlet :
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class CreatePDFServlet extends HttpServlet {

      public void doPost(HttpServletRequest req,    
                         HttpServletResponse resp)
             throws ServletException, IOException {
            doGet(req, resp);
      }

      public void doGet(HttpServletRequest req,
                        HttpServletResponse resp)
             throws ServletException, IOException
      {
            int i = 0;
            int k = 0;
            int maxLength = req.getContentLength();
            byte[] bytes = new byte[maxLength];
            String method = req.getParameter("method");
            String name = req.getParameter("name");
            ServletInputStream si = req.getInputStream();
            while (true)
            {
                  k = si.read(bytes,i,maxLength);
                  i += k;
                  if (k <= 0)
                        break;
            }

            if (bytes != null)
            {
                  ServletOutputStream stream =
                        resp.getOutputStream();
                  resp.setContentType("application/pdf");
                  resp.setContentLength(bytes.length);
                  resp.setHeader("Content-Disposition",method +
                                 ";filename=" + name);
                  stream.write(bytes);
                  stream.flush();
                  stream.close();
            }
            else
            {
                  resp.setContentType("text");
                  resp.getWriter().write("bytes is null");
            }
      }
}


Bon courage my friends!

vendredi 5 octobre 2012

Les ViewStack ne rigolent pas avec leurs fils

Je voudrais vous éviter de vous prendre la tête le jour où vos composants imbriqués (par exemple Container, HBox et VBox) ne prennent plus toute la place, même si vous avez pris la peine de passer sur chacune des balises pour mettre des width="100%" et height="100%"

Ce jour là, si vous restez sans solution jusqu'à 19h30h, et si vous devez corriger ce problème pour que le positionnement des composants soient présentable pour la démo du lendemain à 9h devant la big chef et que vous ne voulez pas rater la séance de 20h de la sortie ciné de l'âge de glace 3 parce que depuis le l'âge de glace 2 vous n'avez jamais eu de fous rires en dehors du boulot... J'arrêtes, ce jour là, essayez de vérifier si dans votre vue il n'y pas un vicieux ViewStack qui empêche ses fils de s'épanouir. Et si c'est le cas, essayez de lui donner une bonne leçon en mettant la propriété resizeToContent de ViewStack à true.
Par exemple :
<mx:ViewStack id="viewsStack
              width="100%"
              height="100%"
              resizeToContent="true"
              horizontalCenter="0">

Bon ciné!!

jeudi 4 octobre 2012

Datagrid checkbox header renderer Fix


Here is a post about datagrid item and header CheckBox renderers in flex 3 : http://shemesh.wordpress.com/2008/05/01/generic-datagrid-checkbox-header-renderer/.

It's well done, and acting directly to modify the data of each row when changing the checkboxes, avoiding to handle more events.

However my need was to make all the items checked at the begining (creationComplete). Unfortunatly when all items are selected at the begining, the header checkbox is not.

So here's my little modification of CheckBoxHeaderRenderer.mxml to fix that :
  
private function checkForSelectedItems():void {
    var dp:ArrayCollection = _dataGrid.dataProvider as ArrayCollection;
    if(dp) {
      var n:Number = 0;
      for(var i:int=0 ; i < dp.length ; i++){
            if(dp[i][_dataField])
                n++
      }
      if(n == dp.length){
            _CBselected = true;
      }else{
            _CBselected = false;
      }
   }
}


Flexivement yours!