Alfresco Quick upload


In Alfresco there is no simple way to modify uploading code. You can't just copy and customize org.alfresco.web.bean.content.AddConteneDialog class and /jsp/content/add-content-dialog.jsp ie you can use add-content-dialog.jsp and modify it, but when you try to use AddContentDialog class updated in your project, it doesn't work. I found somewhere on forums (sry, i can't find a link) that add-content-dialog.jsp is just a page snippet and when you coding your own dialog, you must write code for whole page and there is problem with r:upload component. So i'll try to describe my simple solution for QuickUpload content to Alfresco through a Servlet.

My servlet – UploadAnalysisFileServlet – extends javax.servlet.http.HttpServlet, i'm using both methods – GET and POST too. (If you don't know how servlets work, just look at this tutorial) I'm using asynchronous requests and iframe, which work "behind scene" and after success user can handle some more action. Actions are following:

  1. View page with select file input and upload button in a form 
  2. After file select and upload button press is AJAX Request fired and file and information are transfered between servlet and client
  3. If file is successfully loaded, iframe views a succesfully-uploaded-image.gif and ok button is enabled
  4. QuickUpload bean control is triggered – aspects and properties are added to new content
  5. File is succesfully uploaded and properties setted up, so back to space view

Simplified "action diagram":
 

Image Hosted by ImageShack.us

 
Now let's look inside code snipets; firstly item one, View page with select file input and upload button in a form

<iframe id="dialog:dialog-body:upload_target" src="progress_anim.gif" style="visibility:hidden"></iframe>
<div id='dialog:dialog-body:fileDiv'>
      <h:inputHidden id="alfFileId" value="#{QuickUpload.fileId}" />
      <input type="file" id='dialog:dialog-body:alfFileInput' name="alfFileInput"/>
      <input type="button" value="upload" onclick="sendAjaxRequest();" id='dialog:dialog-body:uploadButton'/>
</div>

 This is just an hidden iframe with content of animation of progress icon and a simple form with upload input type and button, which triggers following JavaScript routine. Ajax calling is based on Prototype JavaScript Framework.
 function sendAjaxRequest(){
    var form = document.getElementById('dialog');
    document.getElementById('dialog:dialog-body:fileDiv').style.visibility = "hidden";

    form.action = '/alfresco/uploadAnalysisFileServlet';
    form.enctype= 'multipart/form-data';
    form.target = 'dialog:dialog-body:upload_target';

    var ifr = document.getElementById('dialog:dialog-body:upload_target');
    ifr.style.visibility = "visible";
    var doc = null;  
    if(ifr.contentDocument)  
      doc = ifr.contentDocument;  // note: this is varying for different browsers!

    var pars = "uploadid=" + document.getElementById("dialog:dialog-body:alfFileId").value;
    var myAjax = new Ajax.Request("/alfresco/uploadAnalysisFileServlet",
         { method: 'get', parameters: pars, onComplete: checkExists });

    form.submit();
    
    form.action = '/alfresco/faces/jsp/dialog/container.jsp';
    form.enctype= 'application/x-www-form-urlencoded';
    form.target = '';
}

First action is getting a form of dialog, then default action of this form is redirected to my servlet. After that is an ID sent through get method to servlet and a file is sent too, viapost metod, thanks to form.submit(). After this sending is dialog form redirected back to original value and onComplete method is called (it just reads a responseText and check, if it is true or false), which enables OK button.
 
How are post and get methods handled in servlet? A org.alfresco.web.bean.FileUploadBean class is used:
 
 public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{
       this.fileUploadBean = new FileUploadBean();
       this.uploadId = request.getParameter("uploadid");
       PrintWriter out = response.getWriter();
       out.println("uploadId = "+this.uploadId);
   }
A doGet method just creates a new FileUploadBean and sets and returns ID of file (I'm using this just for debugging and experimenting purposes, it can all be placed just in a Post method). Now let's handle post method data:
 
public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{
       HttpSession session = request.getSession();
       ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
      
       List<FileItem> fileItems = upload.parseRequest(request);
       for (FileItem item : fileItems){
           if(item.getFieldName().equalsIgnoreCase("alfFileInput")){
               String filename = item.getName();
               filename = FilenameUtils.getName(filename);
               final File tempFile = TempFileProvider.createTempFile("alfresco", ".upload");
               item.write(tempFile);
               this.fileUploadBean.setFile(tempFile);
               this.fileUploadBean.setFileName(filename);
               this.fileUploadBean.setFilePath(tempFile.getAbsolutePath());
           }
       }
      
       session.setAttribute(FileUploadBean.getKey(uploadId), this.fileUploadBean);
       response.setContentType("text/html");
       PrintWriter out = response.getWriter();
       out.println("<img src="/alfresco/images/icons/deploy_successful.gif"/>");
   }
This snippet is hardly simplified, but idea is still readable: it reads all file items and if one of them is our file input (alfFileInput), temporary file is created and fileUploadBean properties are set. Then is set an attribute in a session – whole fileUploadBean and a response is sent back to JavaScript client – view of succesfull_upload inside iframe.
 
At this phase a user can do "OK", so QuickUpload's finishImpl method is triggered. It handles a uploaded file following simple way:
FacesContext ctx = FacesContext.getCurrentInstance();
FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
                                get(FileUploadBean.FILE_UPLOAD_BEAN_NAME.concat("-"+this.getFileId()));
       
if(fileBean != null){
    this.file = fileBean.getFile();
    this.fileName = fileBean.getFileName();
 
    NodeRef spaceRef = this.navigator.getCurrentNode().getNodeRef();
    FileInfo fileInfo = this.getFileFolderService().create(spaceRef, fileBean.getFileName(), ContentModel.TYPE_CONTENT);
    NodeRef fileNodeRef = fileInfo.getNodeRef();
               
    Map<QName, Serializable> fileDesc = new HashMap<QName, Serializable>(3, 1.0f);
    fileDesc.put(ContentModel.PROP_TITLE, this.fileName);
 
    ContentWriter writer = this.contentService.getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
    writer.putContent(this.file);
}
Firstly a FileUploadBean is extracted back from SessionMap, then a content inside currentNode is created with specified parameters (it is also possible to add some aspects and properties there). After all that just "return outcome;" and hooray, we have simple working QuickUpload routine for Alfresco ;-).

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *