Changeset 5395


Ignore:
Timestamp:
Aug 27, 2010, 2:55:56 PM (12 years ago)
Author:
Nicklas Nordborg
Message:

Fixes #738: Implement file upload as a pure servlet

It is not the file upload itself that is the real problem, it is the fact that the upload is sent to a hidden frame and that it is difficult to handle errors (eg. show them to the user). The new solution is to simply let the error be generated in the hidden frame and then use a javascript callback in the parent window to re-size the frames so that the upload-frame becomes visible instead.

I have also got rid of the non-ajax version of progress reporter since this could also cause problems. The progress reporting is no longer responsible for any error handling (since it is possible for an error to happen before the progress reporting infrastructure has been setup).

Location:
trunk
Files:
2 added
2 deleted
9 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/config/dist/web.xml

    r5114 r5395  
    113113  </servlet-mapping>
    114114
     115  <!-- The Upload servlet used to upload files  -->
     116  <servlet>
     117    <servlet-name>upload</servlet-name>
     118    <servlet-class>
     119      net.sf.basedb.clients.web.servlet.Upload
     120    </servlet-class>
     121  </servlet>
     122  <servlet-mapping>
     123    <servlet-name>upload</servlet-name>
     124    <url-pattern>/filemanager/upload/Upload</url-pattern>
     125  </servlet-mapping>
    115126
    116127  <!-- The SpotImage servlet used to view spot images in a raw bioassay -->
  • trunk/www/exception/duplicate_wizard.jsp

    r4510 r5395  
    4848%>
    4949<base:page type="default" menu="exception" title="Another plug-in wizard is active">
    50 <base:head>
     50<base:head scripts="exception.js">
    5151  <script language="JavaScript">
    52   function fixWindow()
    53   {
    54     if (window.opener != null)
    55     {
    56       // popup window --> Hide menubar
    57       Main.hide('menubar');
    58       var width = Main.getWindowWidth();
    59       var height = Main.getWindowHeight();
    60       if (height < 400) height = 400;
    61       if (width < 600) width = 600; // >
    62       window.resizeTo(width, height);
    63     }
    64     else
    65     {
    66       // Hide close button
    67       Main.hide('close');
    68       // If inside a second frameset, hide menubar
    69       if (window.parent != window.top)
    70       {
    71         Main.hide('menubar');
    72       }
    73     }
    74   }
    7552  function goNext()
    7653  {
     
    8259  </script>
    8360</base:head>
    84 <base:body onload="fixWindow()">
     61<base:body onload="Exception.fixWindow(false)">
    8562
    8663  <div align="center">
     
    9370  <tr>
    9471    <td id="next" width="50%"><base:button onclick="goNext();" title="Continue" image="gonext.gif" /></td>
    95     <td id="close" width="50%"><base:button onclick="window.close();" title="Cancel" /></td>
     72    <td id="close" width="50%"><base:button onclick="window.top.close();" title="Cancel" /></td>
    9673  </tr>
    9774  </table>
  • trunk/www/exception/exception.jsp

    r4889 r5395  
    110110%>
    111111<base:page type="default" menu="exception" title="Unexpected error">
    112 <base:head>
    113   <script language="JavaScript">
    114   // Hide and display some elements that should not be displayed at all times
    115   function fixWindow()
    116   {
    117     if (history.length <= 1) // >
    118     {
    119       Main.hide('goback');
    120     }
    121     if (window.top != null && window.top.opener != null)
    122     {
    123       // popup window --> Hide menubar
    124       Main.hide('menubar');
    125       var width = Main.getWindowWidth();
    126       var height = Main.getWindowHeight();
    127       if (height < 600) height = 600;
    128       if (width < 800) width = 800; // >
    129       window.resizeTo(width, height);
    130     }
    131     else
    132     {
    133       // Hide close button
    134       Main.hide('close');
    135       // If inside a second frameset, hide menubar
    136       if (window.parent != window.top)
    137       {
    138         Main.hide('menubar');
    139       }
    140     }
    141   }
    142   </script>
    143 </base:head>
    144 <base:body onload="fixWindow()">
     112<base:head scripts="exception.js" />
     113<base:body onload="Exception.fixWindow(true)">
    145114  <base:note type="error" title="<%=exceptionClassName + " on page "+request.getAttribute("javax.servlet.error.request_uri")%>"
    146115    style="width:90%;" messagestyle="height: 450px;">
     
    238207  <base:buttongroup align="center">
    239208    <base:button id="goback" onclick="<%="history.go(-1)"%>" title="Back"/>
    240     <base:button id="close" onclick="<%="window.close()"%>" title="Close"/>
     209    <base:button id="close" onclick="<%="window.top.close()"%>" title="Close"/>
    241210    <base:button id="reportbug" onclick="<%="window.open('"+reportbuglink+"','Reportbug')"%>"
    242211      title="Report bug&hellip;" image="bug.gif"
  • trunk/www/exception/invalid_data.jsp

    r4889 r5395  
    5858%>
    5959<base:page type="default" menu="exception" title="Invalid data">
    60 <base:head>
    61   <script language="JavaScript">
    62   function fixWindow()
    63   {
    64     if (history.length <= 1) // >
    65     {
    66       Main.hide('goback');
    67     }
    68     if (window.opener != null)
    69     {
    70       // popup window --> Hide menubar
    71       Main.hide('menubar');
    72       var width = Main.getWindowWidth();
    73       var height = Main.getWindowHeight();
    74       if (height < 400) height = 400;
    75       if (width < 600) width = 600; // >
    76       window.resizeTo(width, height);
    77     }
    78     else
    79     {
    80       // Hide close button
    81       Main.hide('close');
    82       // If inside a second frameset, hide menubar
    83       if (window.parent != window.top)
    84       {
    85         Main.hide('menubar');
    86       }
    87     }
    88   }
    89   </script>
    90 </base:head>
    91 <base:body onload="fixWindow()">
     60<base:head scripts="exception.js" />
     61<base:body onload="Exception.fixWindow(false)">
    9262
    9363  <div align="center">
     
    10070  <tr>
    10171    <td id="goback" width="50%"><base:button onclick="history.go(-1);" title="Back" /></td>
    102     <td id="close" width="50%"><base:button onclick="window.close();" title="Close" /></td>
     72    <td id="close" width="50%"><base:button onclick="window.top.close();" title="Close" /></td>
    10373  </tr>
    10474  </table>
  • trunk/www/exception/not_logged_in.jsp

    r4889 r5395  
    5050final String root = request.getContextPath()+"/";
    5151final String redirect = Values.getString((String)request.getAttribute("redirect"));
    52 
    5352%>
    5453<base:page type="default" menu="exception" title="Not logged in">
    55 <base:head scripts="md5.js" styles="login.css">
     54<base:head scripts="md5.js,exception.js" styles="login.css">
    5655  <script language="JavaScript">
    5756  // hide menubar and resize if it is a popup window
    58   function fixWindow()
     57  function init()
    5958  {
    60     if (window.opener != null)
    61     {
    62       // popup window
    63       Main.hide('menubar');
    64       var width = Main.getWindowWidth();
    65       var height = Main.getWindowHeight();
    66       if (height < 400) height = 400;
    67       if (width < 600) width = 600; // >
    68       window.resizeTo(width, height);
    69     }
     59    Exception.fixWindow(true);
    7060    setFocus();
    7161  }
     
    132122  </script>
    133123</base:head>
    134 <base:body onload="fixWindow()">
     124<base:body onload="init()">
    135125  <div align="center">
    136126    <form action="<%=root%>login.jsp?again=1" method="post" name="login" target="Login" onsubmit="return false;">
  • trunk/www/exception/permission_denied.jsp

    r4889 r5395  
    5858%>
    5959<base:page type="default" menu="exception" title="Permission denied">
    60 <base:head>
    61   <script language="JavaScript">
    62   function fixWindow()
    63   {
    64     if (history.length <= 1) // >
    65     {
    66       Main.hide('goback');
    67     }
    68     if (window.opener != null)
    69     {
    70       // popup window --> Hide menubar
    71       Main.hide('menubar');
    72       var width = Main.getWindowWidth();
    73       var height = Main.getWindowHeight();
    74       if (height < 400) height = 400;
    75       if (width < 600) width = 600; // >
    76       window.resizeTo(width, height);
    77     }
    78     else
    79     {
    80       // Hide close button
    81       Main.hide('close');
    82       // If inside a second frameset, hide menubar
    83       if (window.parent != window.top)
    84       {
    85         Main.hide('menubar');
    86       }
    87     }
    88   }
    89   </script>
    90 </base:head>
    91 <base:body onload="fixWindow()">
     60<base:head scripts="exception.js" />
     61<base:body onload="Exception.fixWindow(false)">
    9262
    9363  <div align="center">
     
    10070  <tr>
    10171    <td id="goback" width="50%"><base:button onclick="history.go(-1);" title="Back" /></td>
    102     <td id="close" width="50%"><base:button onclick="window.close();" title="Close" /></td>
     72    <td id="close" width="50%"><base:button onclick="window.top.close();" title="Close" /></td>
    10373  </tr>
    10474  </table>
  • trunk/www/exception/web.jsp

    r4889 r5395  
    5151%>
    5252<base:page type="<%=ex.getPageType()%>" menu="auto" title="<%=ex.getTitle()%>">
    53 <base:head>
    54   <script language="JavaScript">
    55   function fixWindow()
    56   {
    57     if (history.length <= 1) // >
    58     {
    59       Main.hide('goback');
    60     }
    61     if (window.opener != null)
    62     {
    63       // popup window --> Hide menubar
    64       Main.hide('menubar');
    65     }
    66     else
    67     {
    68       // Hide close button
    69       Main.hide('close');
    70       // If inside a second frameset, hide menubar
    71       if (window.parent != window.top)
    72       {
    73         Main.hide('menubar');
    74       }
    75     }
    76   }
    77   </script>
    78 </base:head>
    79 <base:body onload="fixWindow()">
     53<base:head scripts="exception.js" />
     54<base:body onload="Exception.fixWindow(false)">
    8055  <br>
    8156  <div align="center">
     
    9065  <tr>
    9166    <td id="goback" width="50%"><base:button onclick="history.go(-1);" title="Back" /></td>
    92     <td id="close" width="50%"><base:button onclick="window.close();" title="Close" /></td>
     67    <td id="close" width="50%"><base:button onclick="window.top.close();" title="Close" /></td>
    9368  </tr>
    9469  </table>
  • trunk/www/filemanager/upload/index.jsp

    r4889 r5395  
    5555sc.setSessionSetting("UnpackProgress", null);
    5656%>
    57 
    5857<base:page type="frameset" title="Upload file">
    59   <base:head />
    60   <frameset rows="*,0,0" frameborder="no" border="0">
     58  <base:head>
     59  <script language="JavaScript">
     60  // Callback that shows the upload-frame in case of an error
     61  function exceptionHandlerCallback()
     62  {
     63    document.getElementById('main').rows='0,*';
     64  }
     65  </script>
     66  </base:head>
     67  <frameset id="main" rows="*,0" frameborder="no" border="0">
    6168    <frame name="select" src="select.jsp?ID=<%=ID%>&directory_id=<%=directoryId%>&file_id=<%=fileId%>"
    6269      scrolling="no" frameborder="0">
    63     <frame name="progress" scrolling="no" frameborder="0">
    64     <frame name="upload" scrolling="no" frameborder="0">
     70    <frame name="upload" scrolling="auto" frameborder="0">
    6571  </frameset>
    6672</base:page>
  • trunk/www/filemanager/upload/select.jsp

    r4889 r5395  
    187187        Main.hide('selectForm');
    188188        Main.show('progressForm');
    189         if (!sendProgressUpdateWithAjax())
    190         {
    191           window.top.frames['progress'].location.href = 'progress.jsp?ID=<%=ID%>';
    192         }
    193       }
    194     }
    195    
    196     function sendProgressUpdateWithAjax()
     189        sendProgressUpdateRequest();
     190      }
     191    }
     192   
     193    function sendProgressUpdateRequest()
    197194    {
    198195      var request = Ajax.getXmlHttpRequest();
    199       if (request != null)
    200       {
    201         var url = 'progress.jsp?ID=<%=ID%>&ajax=1&'+Math.random();
     196      var url = 'ajax.jsp?ID=<%=ID%>&cmd=GetProgress&'+Math.random();
     197      request.open("GET", url, true);
     198      Ajax.setReadyStateHandler(request, progressUpdateCallback);
     199      request.send(null);
     200    }
     201   
     202    function progressUpdateCallback(request)
     203    {
     204      var response = Ajax.parseResponse(request.responseText);
     205      var progress = response.getElements()[0];
     206      if (progress)
     207      {
     208        var filename = progress['file'];
     209        var transferredBytes = progress['bytes.transferred'];
     210        var totalBytes = progress['bytes.total'];
     211        var timeInSeconds = progress['time.seconds'];
     212        var message = progress['message'];
     213       
     214        displayProgress(filename, transferredBytes, totalBytes, timeInSeconds, message);
     215      }
     216      setTimeout('sendProgressUpdateRequest()', 1500);
     217    }
     218   
     219    function abortUpload()
     220    {
     221      if (confirm('Are you sure you want to abort the upload? It cannot be resumed.'))
     222      {
     223        var request = Ajax.getXmlHttpRequest();
     224        var url = 'ajax.jsp?ID=<%=ID%>&cmd=Abort&'+Math.random();
    202225        request.open("GET", url, true);
    203         Ajax.setReadyStateHandler(request, updateProgressWithAjax);
    204226        request.send(null);
    205       }
    206       return request != null;
    207     }
    208    
    209     function updateProgressWithAjax(request)
    210     {
    211       var response = request.responseText.split(':');
    212       //alert(response[0]+':'+response[1]+':'+response[2]+':'+response[3]+':'+response[4]+':'+response[5]);
    213       displayProgress(response[0],response[1],response[2],response[3],response[4],response.slice(5).join(':'));
    214       setTimeout('sendProgressUpdateWithAjax()', 1500);
    215     }
    216    
    217     function abortUpload()
    218     {
    219       if (confirm('Are you sure you want to abort the upload? It cannot be resumed.'))
    220       {
    221         window.top.frames['progress'].location.href = 'progress.jsp?ID=<%=ID%>&abort=1';
    222227      }
    223228    }
     
    286291    }
    287292   
    288     function displayProgress(fileName, transferredBytes, totalBytes, transferTime, remainTime, unpackMessage)
     293    function displayProgress(fileName, transferredBytes, totalBytes, transferTime, message)
    289294    {
    290295      // File name
     
    305310
    306311      // Times and rate
     312      document.getElementById('transferTime').innerHTML = Numbers.formatSeconds(transferTime);
    307313      var transferRate = transferTime == 0 ? 0 : transferredBytes / transferTime;
    308       document.getElementById('transferTime').innerHTML = Numbers.formatSeconds(transferTime);
    309314      document.getElementById('transferRate').innerHTML = '(' + Numbers.formatBytes(transferRate) + '/s)';
    310       document.getElementById('remainTime').innerHTML = Numbers.formatSeconds(remainTime) + ' (estimated)';
     315      if (transferRate > 0)
     316      {
     317        var remainTime = parseInt((totalBytes-transferredBytes) / transferRate);
     318        document.getElementById('remainTime').innerHTML = Numbers.formatSeconds(remainTime) + ' (estimated)';
     319      }
    311320     
    312321      // Message
    313       if (unpackMessage)
    314       {
    315         document.getElementById('unpackMessage').innerHTML = unpackMessage.replace(/(.*):(.*)/, '<b>$1:</b> $2');
     322      if (message)
     323      {
     324        document.getElementById('message').innerHTML = message.replace(/(.*):(.*)/, '<b>$1:</b> $2');
    316325      }
    317326    }
     
    359368  <p>
    360369  <div id="selectForm">
    361     <form action="upload.jsp?ID=<%=ID%>&directory_id=<%=directory.getId()%>"
     370    <form action="Upload?ID=<%=ID%>&directory_id=<%=directory.getId()%>"
    362371      method="post" name="file" enctype="multipart/form-data" onsubmit="return false;" target="upload">
    363372
     
    580589          <b>Time:</b> <span id="transferTime">0s</span> <span id="transferRate"></span><br>
    581590          <b>Remain:</b> <span id="remainTime">unknown</span><br>
    582           <span id="unpackMessage"></span>
     591          <span id="message"></span>
    583592        </td>
    584593      </tr>
  • trunk/www/filemanager/upload/upload_results.jsp

    r5360 r5395  
    2121  ------------------------------------------------------------------
    2222
    23   This page is used to display the progress of a file upload. The FileUploadProgress
    24   is put into the session setting by the upload.jsp page when the upload is started.
    25   If an exception is thrown during the upload we can get it by checking the
    26   FileUploadProgress.getException() method.
    27  
    28   If we want to abort the upload we use the FileUpload.setAbort() method, which is
    29   detected by the upload process and causes an UploadAbortedException to be thrown.
    30   This exception is also detected by the FileUploadProgress.getException() method
    31   before we display the message about the aborted upload.
    32 
    3323  @author Nicklas
    34   @version 2.0
     24  @version 2.16
    3525--%>
    3626<%@ page session="false"
    37   import="net.sf.basedb.core.SessionControl"
    38   import="net.sf.basedb.core.SimpleProgressReporter"
    39   import="net.sf.basedb.clients.web.Base"
    40   import="net.sf.basedb.util.Values"
    4127  import="net.sf.basedb.clients.web.util.HTML"
    42   import="net.sf.basedb.clients.web.fileupload.FileUploadProgress"
    43   import="net.sf.basedb.clients.web.fileupload.UploadAbortedException"
    4428%>
    45 <%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
    4629<%
    47 final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
    48 final FileUploadProgress progress = (FileUploadProgress)sc.getSessionSetting("FileUploadProgress");
    49 sc.setSessionSetting("FileUploadProgress", null);
    50 sc.setSessionSetting("UnpackProgress", null);
    51 if (progress.getException() != null) throw progress.getException();
     30final String message = request.getParameter("message");
    5231%>
     32<html>
     33<head>
     34  <script language="JavaScript">
     35  function showMessage()
     36  {
     37    window.top.location = '../../common/close_popup.jsp?refresh_opener=1&message=<%=HTML.urlEncode(message)%>';
     38  }
     39  </script>
     40</head>
     41<body onload="showMessage();">
     42</body>
     43</html>
     44
Note: See TracChangeset for help on using the changeset viewer.