EasyUI Forum
March 28, 2024, 03:31:30 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News:
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: File upload example - queue up in JS and status in datagrid  (Read 11545 times)
argumentum
Newbie
*
Posts: 22



View Profile
« on: February 19, 2018, 01:05:45 AM »

I hope this can help you.

It helped me too  Smiley

Now my problem is that I'd like to have a queue of uploads, and upload one by one in the background, using the RowID as reference, but I have no idea on how to go about it. I've tried very many solutions but I'm just not savvy with javascript.

I made a mockup of the concept at http://code.reloado.com/awofin/edit#html,live with this code:
Code:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>jQuery EasyUI Demo - Upload and grid</title>
    <link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/icon.css">
    <link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/demo/demo.css">
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <script type="text/javascript" src="http://www.jeasyui.com/easyui/jquery.easyui.min.js"></script>
<style>
body { font-family: "Verdana"; }
</style>
</head>
<!--    http://code.reloado.com/awofin/edit#html,live    -->
<body>
    <p>Select a row and click upload to add it to the upload queue.<br><br>
If is the first in the queue, it will be queued and uploaded,<br>
otherwise, will be queued, to be next in the queue.<br><br>
Uploading will be finished when all queued files are uploaded.<br><br>
The queue idea is to optimize uploading on low bandwith.</p>
    <div style="margin:20px 0;">
        <a href="javascript:void(0)" class="easyui-linkbutton" onclick="uploadSelected()">Upload for selected</a>
    </div>
    <!-- grid -->
    <table id="dg" title="upload and show status in the grid" style="width:700px;height:400px" data-options="
                rownumbers:true,
                singleSelect:true,
                autoRowHeight:false,
                pagination:true,
                pageSize:10">
        <thead>
            <tr>
                <th field="RowID" width="80">db RowID</th>
                <th field="uploadStatus" width="100">Upload Status</th>
                <th field="name" width="80">Name</th>
                <th field="note" width="110">Note </th>
            </tr>
        </thead>
    </table>
    <!-- grid -->
    <!-- upload dialog-->
    <div id="dlg" class="easyui-dialog" title="Complex Toolbar on Dialog" style="width:400px;height:140px;padding:10px" data-options="
closed: true,
modal: true,
                iconCls: 'icon-save',
                buttons: '#dlg-buttons'
            ">
        <form enctype="multipart/form-data" id="ffUpload" name="ffUpload" method="post">
            <table border="0" style="width:100%">
                <tr>
                    <input class="easyui-filebox" data-options="prompt:'Choose a file...'" style="width:100%"> </tr>
            </table>
        </form>
    </div>
    <div id="dlg-buttons">
        <a href="javascript:void(0)" class="easyui-linkbutton" onclick="javascript:uploadQueue()">Upload</a>
        <a href="javascript:void(0)" class="easyui-linkbutton" onclick="javascript:$('#dlg').dialog('close')">Cancel</a>
    </div>
    <!-- upload dialog-->
    <script>
        var globalRowsData = []; // if this global works, no clue.
        (function($) {
            function pagerFilter(data) {
                if ($.isArray(data)) { // is array
                    data = {
                        total: data.length,
                        rows: data
                    }
                }
                var target = this;
                var dg = $(target);
                var state = dg.data('datagrid');
                var opts = dg.datagrid('options');
                if (!state.allRows) {
                    state.allRows = (data.rows);
                }
                if (!opts.remoteSort && opts.sortName) {
                    var names = opts.sortName.split(',');
                    var orders = opts.sortOrder.split(',');
                    state.allRows.sort(function(r1, r2) {
                        var r = 0;
                        for (var i = 0; i < names.length; i++) {
                            var sn = names[i];
                            var so = orders[i];
                            var col = $(target).datagrid('getColumnOption', sn);
                            var sortFunc = col.sorter || function(a, b) {
                                return a == b ? 0 : (a > b ? 1 : -1);
                            };
                            r = sortFunc(r1[sn], r2[sn]) * (so == 'asc' ? 1 : -1);
                            if (r != 0) {
                                return r;
                            }
                        }
                        return r;
                    });
                }
                var start = (opts.pageNumber - 1) * parseInt(opts.pageSize);
                var end = start + parseInt(opts.pageSize);
                data.rows = state.allRows.slice(start, end);
                return data;
            }

            var loadDataMethod = $.fn.datagrid.methods.loadData;
            var deleteRowMethod = $.fn.datagrid.methods.deleteRow;
            $.extend($.fn.datagrid.methods, {
                clientPaging: function(jq) {
                    return jq.each(function() {
                        var dg = $(this);
                        var state = dg.data('datagrid');
                        var opts = state.options;
                        opts.loadFilter = pagerFilter;
                        var onBeforeLoad = opts.onBeforeLoad;
                        opts.onBeforeLoad = function(param) {
                            state.allRows = null;
                            return onBeforeLoad.call(this, param);
                        }
                        var pager = dg.datagrid('getPager');
                        pager.pagination({
                            onSelectPage: function(pageNum, pageSize) {
                                opts.pageNumber = pageNum;
                                opts.pageSize = pageSize;
                                pager.pagination('refresh', {
                                    pageNumber: pageNum,
                                    pageSize: pageSize
                                });
                                dg.datagrid('loadData', state.allRows);
                            }
                        });
                        $(this).datagrid('loadData', state.data);
                        if (opts.url) {
                            $(this).datagrid('reload');
                        }
                    });
                },
                loadData: function(jq, data) {
                    jq.each(function() {
                        $(this).data('datagrid').allRows = null;
                    });
                    return loadDataMethod.call($.fn.datagrid.methods, jq, data);
                },
                deleteRow: function(jq, index) {
                    return jq.each(function() {
                        var row = $(this).datagrid('getRows')[index];
                        deleteRowMethod.call($.fn.datagrid.methods, $(this), index);
                        var state = $(this).data('datagrid');
                        if (state.options.loadFilter == pagerFilter) {
                            for (var i = 0; i < state.allRows.length; i++) {
                                if (state.allRows[i] == row) {
                                    state.allRows.splice(i, 1);
                                    break;
                                }
                            }
                            $(this).datagrid('loadData', state.allRows);
                        }
                    });
                },
                getAllRows: function(jq) {
                    return jq.data('datagrid').allRows;
                }
            })
        })(jQuery);

        function getData() {
            for (var i = 1; i <= 800; i++) {
                globalRowsData.push({
                    RowID: i,
                    uploadStatus: 'none yet',
                    name: 'Name ' + i,
                    note: 'Note ' + i
                });
            }
            return globalRowsData; // I made it a "global", but I don't know how it'd work in this demo.
        }

        $(function() {
            $('#dg').datagrid({
                data: getData()
            }).datagrid('clientPaging');
        });

function uploadQueue(){
$('#dlg').dialog('close');
$.messager.alert('todo','queue up chosen file<br>and start ulpoad<br>if none is active');
}

        function uploadSelected() { // is gonna be just 1 selected
            var ss = [];
            var rows = $('#dg').datagrid('getSelections');
            if (rows.length < 1) {
                return false;
            }
            for (var i = 0; i < rows.length; i++) {
                var row = rows[i];
                ss.push('<span>' + row.RowID + "<br>" + row.name + "<br>" + row.note + '</span>');
$('#dlg').dialog({title: ' upload for RowID = ' + row.RowID});
            }
$('#dlg').dialog('open');
        }
    </script>
</body>
</html>

I'm stuck until I get this solved.

Thanks

« Last Edit: February 19, 2018, 01:23:15 AM by argumentum » Logged
stworthy
Administrator
Hero Member
*****
Posts: 3581


View Profile Email
« Reply #1 on: February 19, 2018, 08:32:55 AM »

Define a function 'uploadFile' to upload the selected file. When start to uploading a file, update the selected row's status to 'uploading'. When uploading action is finished, update the row's status to 'finished'. Please refer to the code below:

Code:
function uploadQueue(){
  var url = 'upload.php';
  $('#dlg').dialog('close');
  var RowID = $('#RowID').val();
  var file = $('#file').next().find('.textbox-value')[0].files[0];
  if (file){
    var row = $('#dg').datagrid('getSelected');
    var index = $('#dg').datagrid('getRowIndex', row);
    row.uploadStatus = 'uploading';
    row.name = file.name;
    $('#dg').datagrid('refreshRow', index);
    uploadFile(url,RowID, file, function(RowID){
      row.uploadStatus = 'finished';
      $('#dg').datagrid('refreshRow', index);
    })
  }
}
function uploadFile(url, RowID, file, succ){
  var xhr = new XMLHttpRequest();
  var formData = new FormData();
  formData.append('RowID', RowID);
  formData.append('file', file, file.name);
  xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
      if (xhr.status >= 200 && xhr.status <300){
        succ(RowID);
      }
    }
  };
  xhr.open('POST', url, true);
  xhr.withCredentials = true;
  xhr.send(formData);
}
Logged
argumentum
Newbie
*
Posts: 22



View Profile
« Reply #2 on: February 19, 2018, 09:37:26 AM »

Define a function 'uploadFile' to upload the selected file. When start to uploading a file, update the selected row's status to 'uploading'. When uploading action is finished, update the row's status to 'finished'. Please refer to the code below:

Thanks stworthy. Reading the code I see that,
1, there is no error handling or handling of any returned value from upload.php and, (got that part in PS3*)
2, there is no queue list of files.

I find both features important. Could you show me how to code those.

Code:
// upload.php would return $response as:
$response["fileName"] = $fileName;
$response["message"] = 'OK';
$response["error"] = false;
echo json_encode($response);

so the function uploadFile would have something of the like:
Code:
if (xhr.status >= 200 && xhr.status < 300) {
succ(RowID, 'finished', fileName, message);
// and I'd like to get data back from the url
// that could be the fileName used, etc.,

} else {
succ(RowID, 'error', '', xhr.status);
// in case of not "xhr.status 2xx"
}

Thanks


PS: I'm using https://www.jeasyui.com/forum/index.php?topic=7052.msg18466#msg18466 as bases for my code.
I did not include it in the mockup as I thought it would not be needed.

PS2: I've added id="file" class="easyui-filebox" to have a $(#file), now,
in var RowID = $('#RowID').val();, could not find #RowID

*PS3:
Code:
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
var ret = JSON.parse(xhr.responseText);
succ(RowID, ret.message);
} else {
succ(RowID,'error ' + xhr.status);
// in case of not "return 2xx"
}
}


« Last Edit: February 19, 2018, 12:04:22 PM by argumentum » Logged
stworthy
Administrator
Hero Member
*****
Posts: 3581


View Profile Email
« Reply #3 on: February 19, 2018, 06:04:43 PM »

The 'RowID' field should be appended to the form to bind the uploading file with the selected row.
Code:
<form enctype="multipart/form-data" id="ffUpload" name="ffUpload" method="post">
    <table border="0" style="width:100%">
        <tr>
            <input id="RowID" type="hidden" name="RowID">
            <input id="file" class="easyui-filebox" data-options="prompt:'Choose a file...'" style="width:100%"> </tr>
    </table>
</form>

Logged
argumentum
Newbie
*
Posts: 22



View Profile
« Reply #4 on: February 19, 2018, 10:21:15 PM »

The code you've shared is functional and does upload.

The 'RowID' field should be appended to the form to bind the uploading file with the selected row.
As far as I can see, the #RowID does not do anything, so, what is its purpose ?, I don't see the binding.
I assume I am to populate it with the the "db RowID", ..ok, so I can pass the value to my upload.php file. Got it.


Also, as I upload, they all upload concurrently, and part of the idea is having a queue to upload sequentially.
Is important for low bandwidth environments. Would you care to show how it can be queued up ?, I haven't had much luck imagining how to go about it.

Thanks for your patience with me stworthy, I know this question is outside jEasyUI support Smiley
Logged
stworthy
Administrator
Hero Member
*****
Posts: 3581


View Profile Email
« Reply #5 on: February 20, 2018, 12:40:30 AM »

Something likes this.
1. When select a file, don't upload it immediately, push it to the queue.
2. Call 'doUpload' function to start uploading a file in the queue.
3. When upload a file successfully, call 'doUpload' function again to upload another file.

Code:
var queue = [];
function uploadQueue(){
  $('#dlg').dialog('close');
  var row = $('#dg').datagrid('getSelected');
  var RowID = $('#RowID').val();
  var file = $('#file').filebox('files')[0];
  if (file){
    queue.push({
        RowID: RowID,
        row: row,
        file: file
    });
    if (queue.length == 1){
      doUpload();
    }
  }
}
function doUpload(){
    var url = 'upload.php';
    if (queue.length){
        var item = queue.shift();
        uploadFile(url, item.RowID, item.file, function(RowID, status, filename, message){
            //...
            doUpload(); // continue to upload
        });
    }
}
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines Valid XHTML 1.0! Valid CSS!