www/filemanager/upload/upload.js

Code
Comments
Other
Rev Date Author Line
7604 25 Feb 19 nicklas 1 /* $Id $
7604 25 Feb 19 nicklas 2   ------------------------------------------------------------------
7604 25 Feb 19 nicklas 3   Copyright (C) 2013 Nicklas Nordborg
7604 25 Feb 19 nicklas 4
7604 25 Feb 19 nicklas 5   This file is part of BASE - BioArray Software Environment.
7604 25 Feb 19 nicklas 6   Available at http://base.thep.lu.se/
7604 25 Feb 19 nicklas 7
7604 25 Feb 19 nicklas 8   BASE is free software; you can redistribute it and/or
7604 25 Feb 19 nicklas 9   modify it under the terms of the GNU General Public License
7604 25 Feb 19 nicklas 10   as published by the Free Software Foundation; either version 3
7604 25 Feb 19 nicklas 11   of the License, or (at your option) any later version.
7604 25 Feb 19 nicklas 12
7604 25 Feb 19 nicklas 13   BASE is distributed in the hope that it will be useful,
7604 25 Feb 19 nicklas 14   but WITHOUT ANY WARRANTY; without even the implied warranty of
7604 25 Feb 19 nicklas 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7604 25 Feb 19 nicklas 16   GNU General Public License for more details.
7604 25 Feb 19 nicklas 17
7604 25 Feb 19 nicklas 18   You should have received a copy of the GNU General Public License
7604 25 Feb 19 nicklas 19   along with BASE. If not, see <http://www.gnu.org/licenses/>.
7604 25 Feb 19 nicklas 20   ------------------------------------------------------------------
7604 25 Feb 19 nicklas 21
7604 25 Feb 19 nicklas 22   @author Nicklas
7604 25 Feb 19 nicklas 23 */
7604 25 Feb 19 nicklas 24 'use strict';
7604 25 Feb 19 nicklas 25
7604 25 Feb 19 nicklas 26 var Upload = function()
7604 25 Feb 19 nicklas 27 {
7604 25 Feb 19 nicklas 28   var upload = {};
7604 25 Feb 19 nicklas 29   
7985 22 Jun 21 nicklas 30   var uploadRequest;
7985 22 Jun 21 nicklas 31   
7604 25 Feb 19 nicklas 32   /**
7604 25 Feb 19 nicklas 33     Initialize the page.
7604 25 Feb 19 nicklas 34   */
7604 25 Feb 19 nicklas 35   upload.initPage = function()
7604 25 Feb 19 nicklas 36   {
7604 25 Feb 19 nicklas 37     var pageId = Doc.getPageId();
7604 25 Feb 19 nicklas 38     if (pageId == 'select-file')
7604 25 Feb 19 nicklas 39     {
7604 25 Feb 19 nicklas 40       // Zip formats
7604 25 Feb 19 nicklas 41       upload.initZipFormats();
7985 22 Jun 21 nicklas 42       Events.addEventHandler('zipUnpack', 'click', upload.unpackZipOnClick);
7604 25 Feb 19 nicklas 43       
7604 25 Feb 19 nicklas 44       // Upload+Close buttons
7604 25 Feb 19 nicklas 45       Buttons.addClickHandler('btnUpload', upload.doUpload);
7604 25 Feb 19 nicklas 46       Buttons.addClickHandler('close', App.closeWindow);
7604 25 Feb 19 nicklas 47       Buttons.addClickHandler('btnAbort', upload.abortUpload);
7604 25 Feb 19 nicklas 48
7604 25 Feb 19 nicklas 49       // File
7604 25 Feb 19 nicklas 50       Events.addEventHandler('the_file', 'change', upload.fileOnChange);
7604 25 Feb 19 nicklas 51       
7604 25 Feb 19 nicklas 52       // Error handling
7985 22 Jun 21 nicklas 53       Buttons.addClickHandler('failClose', App.closeWindow);
7604 25 Feb 19 nicklas 54     }
7604 25 Feb 19 nicklas 55   }
7604 25 Feb 19 nicklas 56
7604 25 Feb 19 nicklas 57   upload.validateFile = function()
7604 25 Feb 19 nicklas 58   {
7604 25 Feb 19 nicklas 59     var frm = document.forms['file'];
7604 25 Feb 19 nicklas 60     if (Strings.trim(frm.the_file.value) == '')
7604 25 Feb 19 nicklas 61     {
7604 25 Feb 19 nicklas 62       Forms.showNotification(frm.the_file, 'You must select a file to upload');
7604 25 Feb 19 nicklas 63       return false;
7604 25 Feb 19 nicklas 64     }
7604 25 Feb 19 nicklas 65     return true;
7604 25 Feb 19 nicklas 66   }
7604 25 Feb 19 nicklas 67   
7604 25 Feb 19 nicklas 68   // Submit the form
7604 25 Feb 19 nicklas 69   upload.doUpload = function()
7604 25 Feb 19 nicklas 70   {
7604 25 Feb 19 nicklas 71     var frm = document.forms['file'];
7604 25 Feb 19 nicklas 72     if (upload.validateFile())
7604 25 Feb 19 nicklas 73     {
7985 22 Jun 21 nicklas 74       var upl = new FormData();
7985 22 Jun 21 nicklas 75       
7604 25 Feb 19 nicklas 76       // Copy form values so they are sent BEFORE the file
7985 22 Jun 21 nicklas 77       upl.set('check_md5', frm.check_md5 && frm.check_md5.checked ? "1" : "0");
7985 22 Jun 21 nicklas 78       upl.set('write_protected', frm.write_protected.checked ? "1" : "0");
7985 22 Jun 21 nicklas 79       upl.set('replace_existing', frm.replace_existing && frm.replace_existing.checked ? "1" : "0");
7985 22 Jun 21 nicklas 80       upl.set('compressed', frm.compressed && frm.compressed.value);
7985 22 Jun 21 nicklas 81       if (frm.zip_format)
7604 25 Feb 19 nicklas 82       {
7985 22 Jun 21 nicklas 83         upl.set('zip_format', frm.zip_format.value);
7985 22 Jun 21 nicklas 84         upl.set('zip_unpack', frm.zip_unpack.checked ? "1" : "0");
7985 22 Jun 21 nicklas 85         upl.set('zip_overwrite', frm.zip_overwrite.checked ? "1" : "0");
7985 22 Jun 21 nicklas 86         upl.set('zip_keep', frm.zip_keep.checked ? "1" : "0");
7604 25 Feb 19 nicklas 87       }
7985 22 Jun 21 nicklas 88       upl.set('characterSet', frm.charset.value);
7985 22 Jun 21 nicklas 89       upl.set('subtype_id', frm.subtype_id.value);
7985 22 Jun 21 nicklas 90       upl.set('description', frm.description.value);
7985 22 Jun 21 nicklas 91       upl.set('the_file', frm.the_file.files[0]);
7985 22 Jun 21 nicklas 92     
7985 22 Jun 21 nicklas 93       var url = 'Upload?ID='+App.getSessionId();
7985 22 Jun 21 nicklas 94       url += '&directory_id='+Data.get('page-data', 'directory-id');
7985 22 Jun 21 nicklas 95       
7985 22 Jun 21 nicklas 96       uploadRequest = Ajax.getXmlHttpRequest();
7985 22 Jun 21 nicklas 97       Ajax.setReadyStateHandler(uploadRequest, upload.uploadComplete, upload.uploadComplete);
7985 22 Jun 21 nicklas 98       uploadRequest.open('POST', url, true);
7985 22 Jun 21 nicklas 99       uploadRequest.send(upl);
7985 22 Jun 21 nicklas 100     
7604 25 Feb 19 nicklas 101       Doc.hide('selectForm');
7604 25 Feb 19 nicklas 102       Doc.show('progressForm');
7604 25 Feb 19 nicklas 103       upload.sendProgressUpdateRequest();
7604 25 Feb 19 nicklas 104     }
7604 25 Feb 19 nicklas 105   }
7604 25 Feb 19 nicklas 106   
7985 22 Jun 21 nicklas 107   upload.uploadComplete = function(request)
7985 22 Jun 21 nicklas 108   {
7986 29 Jun 21 nicklas 109     // If we have called uploadRequest.abort()
7986 29 Jun 21 nicklas 110     // we do not need error handling here
7986 29 Jun 21 nicklas 111     if (request.status == 0) return;
7985 22 Jun 21 nicklas 112     var result = {};
7985 22 Jun 21 nicklas 113     try
7985 22 Jun 21 nicklas 114     {
7985 22 Jun 21 nicklas 115       var contentType = request.getResponseHeader('Content-Type');
7985 22 Jun 21 nicklas 116       if (request.status != 200 || contentType.indexOf('json') == -1)
7985 22 Jun 21 nicklas 117       {
7985 22 Jun 21 nicklas 118         throw new Error(request.responseText);
7985 22 Jun 21 nicklas 119       }
7985 22 Jun 21 nicklas 120       result = JSON.parse(request.responseText);
7985 22 Jun 21 nicklas 121     }
7985 22 Jun 21 nicklas 122     catch (err)
7985 22 Jun 21 nicklas 123     {
7985 22 Jun 21 nicklas 124       result.status = 'error';
7985 22 Jun 21 nicklas 125       result.message = err;
7985 22 Jun 21 nicklas 126     }    
7985 22 Jun 21 nicklas 127     if (result.status == 'ok')
7985 22 Jun 21 nicklas 128     {
7985 22 Jun 21 nicklas 129       var url = '../../common/close_popup.jsp?refresh_opener=1&message='+encodeURIComponent(result.message);
7985 22 Jun 21 nicklas 130       window.top.location = url;
7985 22 Jun 21 nicklas 131     }
7985 22 Jun 21 nicklas 132     else
7985 22 Jun 21 nicklas 133     {
7986 29 Jun 21 nicklas 134       upload.displayError(result);
7985 22 Jun 21 nicklas 135     }
7985 22 Jun 21 nicklas 136   }
7985 22 Jun 21 nicklas 137
7604 25 Feb 19 nicklas 138   upload.fileOnChange = function()
7604 25 Feb 19 nicklas 139   {
7604 25 Feb 19 nicklas 140     var frm = document.forms['file'];
7604 25 Feb 19 nicklas 141     var filename = frm.the_file.value;
7604 25 Feb 19 nicklas 142     var isZip = false;
7604 25 Feb 19 nicklas 143     var zipIndex = 0;
7604 25 Feb 19 nicklas 144     var longestMatch = 0;
7604 25 Feb 19 nicklas 145     
7985 22 Jun 21 nicklas 146     for (var i = 0; i < frm.zip_format.length; i++)
7604 25 Feb 19 nicklas 147     {
7985 22 Jun 21 nicklas 148       var zf = frm.zip_format[i].zipFormat;
7604 25 Feb 19 nicklas 149       var matchLength = upload.matchesZipExtension(zf, filename);
7604 25 Feb 19 nicklas 150       if (matchLength > longestMatch)
7604 25 Feb 19 nicklas 151       {
7604 25 Feb 19 nicklas 152         isZip = true;
7604 25 Feb 19 nicklas 153         zipIndex = i;
7604 25 Feb 19 nicklas 154         longestMatch = matchLength;
7604 25 Feb 19 nicklas 155       }
7604 25 Feb 19 nicklas 156     }
7604 25 Feb 19 nicklas 157     
7985 22 Jun 21 nicklas 158     if (frm.zip_format)
7604 25 Feb 19 nicklas 159     {
7985 22 Jun 21 nicklas 160       frm['zip_format'].disabled = !isZip;
7985 22 Jun 21 nicklas 161       frm['zip_format'].selectedIndex = zipIndex;
7985 22 Jun 21 nicklas 162       frm['zip_unpack'].disabled = !isZip;
7985 22 Jun 21 nicklas 163       frm['zip_overwrite'].disabled = !isZip || !frm['zip_unpack'].checked;
7985 22 Jun 21 nicklas 164       frm['zip_keep'].disabled = !isZip || !frm['zip_unpack'].checked;
7985 22 Jun 21 nicklas 165       frm['compressed'].disabled = isZip;
7604 25 Feb 19 nicklas 166       if (isZip)
7604 25 Feb 19 nicklas 167       {
7604 25 Feb 19 nicklas 168         // Select '-auto-' if present, otherwise 'no'
7985 22 Jun 21 nicklas 169         Forms.selectListOption(frm['compressed'], '0');
7985 22 Jun 21 nicklas 170         Forms.selectListOption(frm['compressed'], '');
7604 25 Feb 19 nicklas 171       }
7604 25 Feb 19 nicklas 172     }
7604 25 Feb 19 nicklas 173   }
7604 25 Feb 19 nicklas 174
7604 25 Feb 19 nicklas 175   upload.initZipFormats = function()
7604 25 Feb 19 nicklas 176   {
7604 25 Feb 19 nicklas 177     var frm = document.forms['file'];
7604 25 Feb 19 nicklas 178     var zipFormats = Data.json('page-data', 'zip-formats');
7604 25 Feb 19 nicklas 179     
7604 25 Feb 19 nicklas 180     for (var i = 0; i < zipFormats.length; i++)
7604 25 Feb 19 nicklas 181     {
7604 25 Feb 19 nicklas 182       var zf = zipFormats[i];
7604 25 Feb 19 nicklas 183       var option = new Option(upload.getFullZipFormatName(zf), zf.id);
7985 22 Jun 21 nicklas 184       frm.zip_format[frm.zip_format.length] = option;
7604 25 Feb 19 nicklas 185       option.zipFormat = zf;
7604 25 Feb 19 nicklas 186     }
7604 25 Feb 19 nicklas 187   }
7604 25 Feb 19 nicklas 188
7604 25 Feb 19 nicklas 189   upload.getFullZipFormatName = function(zipFormat)
7604 25 Feb 19 nicklas 190   {
7604 25 Feb 19 nicklas 191     var s = zipFormat.name + " [";
7604 25 Feb 19 nicklas 192     for (var i = 0; i < zipFormat.extensions.length; i++)
7604 25 Feb 19 nicklas 193     {
7604 25 Feb 19 nicklas 194       if (i > 0) s += ', ';
7604 25 Feb 19 nicklas 195       s += '*.' + zipFormat.extensions[i];
7604 25 Feb 19 nicklas 196     }
7604 25 Feb 19 nicklas 197     s += ']';
7604 25 Feb 19 nicklas 198     return s;
7604 25 Feb 19 nicklas 199   }
7604 25 Feb 19 nicklas 200   
7604 25 Feb 19 nicklas 201   upload.matchesZipExtension = function(zipFormat, filename)
7604 25 Feb 19 nicklas 202   {
7604 25 Feb 19 nicklas 203     var longestMatch = 0;
7604 25 Feb 19 nicklas 204     for (var i = 0; i < zipFormat.extensions.length; i++)
7604 25 Feb 19 nicklas 205     {
7604 25 Feb 19 nicklas 206       var ext = '.' + zipFormat.extensions[i];
7604 25 Feb 19 nicklas 207       var index = filename.lastIndexOf(ext);
7604 25 Feb 19 nicklas 208       if (index > 0 && (index + ext.length == filename.length))
7604 25 Feb 19 nicklas 209       {
7604 25 Feb 19 nicklas 210         if (ext.length > longestMatch)
7604 25 Feb 19 nicklas 211         {
7604 25 Feb 19 nicklas 212           longestMatch = ext.length;
7604 25 Feb 19 nicklas 213         }
7604 25 Feb 19 nicklas 214       }
7604 25 Feb 19 nicklas 215     }
7604 25 Feb 19 nicklas 216     return longestMatch;
7604 25 Feb 19 nicklas 217   }
7604 25 Feb 19 nicklas 218   
7604 25 Feb 19 nicklas 219   upload.unpackZipOnClick = function()
7604 25 Feb 19 nicklas 220   {
7604 25 Feb 19 nicklas 221     var frm = document.forms['file'];
7985 22 Jun 21 nicklas 222     var checked = frm['zip_unpack'].checked;
7985 22 Jun 21 nicklas 223     if (!checked) frm['zip_keep'].checked = true;
7985 22 Jun 21 nicklas 224     frm['zip_overwrite'].disabled = !checked;
7985 22 Jun 21 nicklas 225     frm['zip_keep'].disabled = !checked;
7604 25 Feb 19 nicklas 226   }
7604 25 Feb 19 nicklas 227
7604 25 Feb 19 nicklas 228   upload.sendProgressUpdateRequest = function()
7604 25 Feb 19 nicklas 229   {
7604 25 Feb 19 nicklas 230     var request = Ajax.getXmlHttpRequest();
7604 25 Feb 19 nicklas 231     var url = 'ajax.jsp?ID='+App.getSessionId();
7604 25 Feb 19 nicklas 232     url += '&cmd=GetProgress&'+Math.random();
7604 25 Feb 19 nicklas 233     request.open("GET", url, true);
7604 25 Feb 19 nicklas 234     Ajax.setReadyStateHandler(request, upload.progressUpdateCallback);
7604 25 Feb 19 nicklas 235     request.send(null);
7604 25 Feb 19 nicklas 236   }
7604 25 Feb 19 nicklas 237   
7604 25 Feb 19 nicklas 238   upload.progressUpdateCallback = function(request)
7604 25 Feb 19 nicklas 239   {
7604 25 Feb 19 nicklas 240     var progress = JSON.parse(request.responseText);
7986 29 Jun 21 nicklas 241     if (progress)
7604 25 Feb 19 nicklas 242     {
7986 29 Jun 21 nicklas 243       if (progress.status == 'ok')
7986 29 Jun 21 nicklas 244       {
7986 29 Jun 21 nicklas 245         if (progress.file)
7986 29 Jun 21 nicklas 246         {
7986 29 Jun 21 nicklas 247           var filename = progress.file;
7986 29 Jun 21 nicklas 248           var transferredBytes = progress.transferredBytes;
7986 29 Jun 21 nicklas 249           var totalBytes = progress.totalBytes;
7986 29 Jun 21 nicklas 250           var timeInSeconds = progress.timeInSeconds;
7986 29 Jun 21 nicklas 251           var message = progress.message;
7986 29 Jun 21 nicklas 252           upload.displayProgress(filename, transferredBytes, totalBytes, timeInSeconds, message);
7986 29 Jun 21 nicklas 253         }
7986 29 Jun 21 nicklas 254       }
7986 29 Jun 21 nicklas 255       else
7986 29 Jun 21 nicklas 256       {
7986 29 Jun 21 nicklas 257         upload.displayError(progress);
7986 29 Jun 21 nicklas 258         uploadRequest.abort(); // Important!! Otherwise the browser may try to re-send the request
7986 29 Jun 21 nicklas 259         return;
7986 29 Jun 21 nicklas 260       }
7604 25 Feb 19 nicklas 261     }
7604 25 Feb 19 nicklas 262     setTimeout(upload.sendProgressUpdateRequest, 1500);
7604 25 Feb 19 nicklas 263   }
7604 25 Feb 19 nicklas 264
7604 25 Feb 19 nicklas 265   
7604 25 Feb 19 nicklas 266   upload.displayProgress = function(fileName, transferredBytes, totalBytes, transferTime, message)
7604 25 Feb 19 nicklas 267   {
7604 25 Feb 19 nicklas 268     // File name
7604 25 Feb 19 nicklas 269     Doc.element('fileName').innerHTML = 'Uploading ' + fileName + '...';
7604 25 Feb 19 nicklas 270       
7604 25 Feb 19 nicklas 271     // Percent done
7604 25 Feb 19 nicklas 272     var percentDone = totalBytes == 0 ? 0 : Math.round(100 * transferredBytes / totalBytes);
7604 25 Feb 19 nicklas 273     Doc.element('percentText').innerHTML = percentDone+'%';
7604 25 Feb 19 nicklas 274     var doneElement = Doc.element('percentDone');
7604 25 Feb 19 nicklas 275     doneElement.style.width = percentDone+'%';
7604 25 Feb 19 nicklas 276     var remainElement = Doc.element('percentRemain');
7604 25 Feb 19 nicklas 277     remainElement.style.width = (100-percentDone)+'%';
7604 25 Feb 19 nicklas 278     if (percentDone == 100) Doc.hide('percentRemain');
7604 25 Feb 19 nicklas 279     
7604 25 Feb 19 nicklas 280     // Bytes
7604 25 Feb 19 nicklas 281     Doc.element('transferredBytes').innerHTML = Numbers.formatBytes(transferredBytes);
7604 25 Feb 19 nicklas 282     Doc.element('totalBytes').innerHTML = Numbers.formatBytes(totalBytes);
7604 25 Feb 19 nicklas 283
7604 25 Feb 19 nicklas 284     // Times and rate
7604 25 Feb 19 nicklas 285     Doc.element('transferTime').innerHTML = Numbers.formatSeconds(transferTime);
7604 25 Feb 19 nicklas 286     var transferRate = transferTime == 0 ? 0 : transferredBytes / transferTime;
7604 25 Feb 19 nicklas 287     Doc.element('transferRate').innerHTML = '(' + Numbers.formatBytes(transferRate) + '/s)';
7604 25 Feb 19 nicklas 288     if (transferRate > 0)
7604 25 Feb 19 nicklas 289     {
7604 25 Feb 19 nicklas 290       var remainTime = parseInt((totalBytes-transferredBytes) / transferRate);
7604 25 Feb 19 nicklas 291       Doc.element('remainTime').innerHTML = Numbers.formatSeconds(remainTime) + ' (estimated)';
7604 25 Feb 19 nicklas 292     }
7604 25 Feb 19 nicklas 293     
7604 25 Feb 19 nicklas 294     // Message
7604 25 Feb 19 nicklas 295     if (message)
7604 25 Feb 19 nicklas 296     {
7985 22 Jun 21 nicklas 297       Doc.element('message').innerHTML = message.replace(/(.*):(.*)/, '<th>$1</th><td>$2</td>');
7604 25 Feb 19 nicklas 298     }
7985 22 Jun 21 nicklas 299     else
7985 22 Jun 21 nicklas 300     {
7985 22 Jun 21 nicklas 301       Doc.element('message').innerHTML = '';
7985 22 Jun 21 nicklas 302     }
7604 25 Feb 19 nicklas 303   }
7604 25 Feb 19 nicklas 304
7986 29 Jun 21 nicklas 305   upload.displayError = function(result)
7986 29 Jun 21 nicklas 306   {
7986 29 Jun 21 nicklas 307     Doc.show('uploadFailed');
7986 29 Jun 21 nicklas 308     Doc.hide('progressForm');
7986 29 Jun 21 nicklas 309     Doc.element('failTitle').innerHTML = result.title || 'File upload failed';
7986 29 Jun 21 nicklas 310     Doc.element('failMessage').innerHTML = result.message || result.stacktrace;
7986 29 Jun 21 nicklas 311     if (result.status == 'abort') setTimeout(App.closeWindow, 1500);
7986 29 Jun 21 nicklas 312   }
7604 25 Feb 19 nicklas 313
7604 25 Feb 19 nicklas 314   upload.abortUpload = function()
7604 25 Feb 19 nicklas 315   {
7604 25 Feb 19 nicklas 316     if (confirm('Are you sure you want to abort the upload? It cannot be resumed.'))
7604 25 Feb 19 nicklas 317     {
7604 25 Feb 19 nicklas 318       /*
7986 29 Jun 21 nicklas 319       Aborting is tricky. See tickets:
7986 29 Jun 21 nicklas 320       http://base.thep.lu.se/ticket/2018
7986 29 Jun 21 nicklas 321       http://base.thep.lu.se/ticket/2019
7986 29 Jun 21 nicklas 322       
7986 29 Jun 21 nicklas 323       Sending "Abort" command to the server AND 
7986 29 Jun 21 nicklas 324       uploadRequest.abort() should tell both ends.
7986 29 Jun 21 nicklas 325       The "abort" is catched by the progress updater that
7986 29 Jun 21 nicklas 326       also display the error message.
7604 25 Feb 19 nicklas 327       */
7604 25 Feb 19 nicklas 328       var request = Ajax.getXmlHttpRequest();
7604 25 Feb 19 nicklas 329       var url = 'ajax.jsp?ID='+App.getSessionId();
7604 25 Feb 19 nicklas 330       url += '&cmd=Abort&'+Math.random();
7604 25 Feb 19 nicklas 331       request.open("GET", url, true);
7604 25 Feb 19 nicklas 332       request.send(null);
7985 22 Jun 21 nicklas 333
7985 22 Jun 21 nicklas 334       uploadRequest.abort();
7604 25 Feb 19 nicklas 335     }
7604 25 Feb 19 nicklas 336   }
7604 25 Feb 19 nicklas 337
7604 25 Feb 19 nicklas 338   return upload;
7604 25 Feb 19 nicklas 339 }();
7604 25 Feb 19 nicklas 340
7604 25 Feb 19 nicklas 341 Doc.onLoad(Upload.initPage);