2

My problem is exactly the same that Monker has posted on here: background file uploader?

Summarizing the problem, on a web page:

  • User clicks Upload File
  • User selects a large File to upload
  • User clicks "UPLOAD" button
  • Application says "your file is being uploaded. You will be notified when it's complete"
  • User continues to use the application as normal, or maybe another window or light box appear showing a progress bar.

Why am I posting here again?

  • My reputation doesn't let me do comments or answer on that post.
  • I wanna show you all the things I have tried with code
  • The post doesnt have a good answer yet.

Some users suggest that we use a 3rd part component like Telerik but using the demo we can see that it freezes the page while file is uploading. I have made a proof of concepts with a lot of ftp components and now I am using one called ChlikatDotNet4, it allows us to start an asynchronous file upload method which seems to solve the problem, but is not so easy like that and I will show you why.

I have made a simple ftp upload web application in ASP.NET MVC 4 using the ChilkatDotNet4.dll, it access a ftp server hosted in my workgroup network. This is the code in my index page with a input to load the file and a submit button:

@using (Html.BeginForm("TesteUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table>
        <tr>
            <td>
                <label>Arquivo: </label>
            </td>
            <td>
                <input type="file" id="PathArquivo" name="PathArquivo"/>
            </td>
        </tr>
        <br/>
        <br/>
</table>
<input type="submit" id="submit_upload" name="submit_upload" value="UPLOAD" />
}

On the controller:

public ActionResult TesteUpload(HttpPostedFileBase PathArquivo)
{

    Ftp2 ftp = new Ftp2();

    //Here goes the hided code to set up the connection parameters to the FTP Server

    if (ftp.Connect())
        {

            //Start the asynchronous method 
            bool sucesso = ftp.AsyncPutFileStart(newName, remotePath + "/" + Path.GetFileName(PathArquivo.FileName));

            //Separate thread for long running operation
            if (sucesso)
            {
                ThreadPool.QueueUserWorkItem(delegate
                {
                    while (!ftp.AsyncFinished)
                    {
                        //Get percent of file uploading 
                        ulong bytesTotal = (ulong)st.Length;
                        ulong bytesSent = (ftp.AsyncBytesSent > 0 ? ftp.AsyncBytesSent : 1);

                        //Separated class with a static int to hold the value
                        Progresso.progresso = (int)((bytesSent * 100) / bytesTotal);
                    }

                    if (ftp.AsyncFinished)
                    {
                        Progresso.progresso = 100;
                    }

                });                    
            }

            ftp.Disconnect();


        }

    return PartialView("TesteDownload");
}

//Action to get the current progress
[NoCache]
public ActionResult StatusUpload()
{
    int operationProgress = Progresso.progresso;

    return Json(new { progress = operationProgress }, JsonRequestBehavior.AllowGet);
}

On the TesteDownload.cshtml source code:

<div>

    <label id="progressLabel"></label><label>%</label>

    <div id="progressTimer"></div>

</div>



<script type="text/javascript">

    past = null;

    $.updateProgress = function () {
        //Getting current operation progress
        $.get('@Url.Action("StatusUpload")', function(data) {

            //Updating progress
            $("#progressLabel").text(data.progress);

            //If operation is complete
            if (data.progress >= 100) {
                $("#progressbarLabel").text(100);
            }
            //If not
            else {
                //Reset timer and call me again
                setTimeout($.updateProgress, 500);
            }

            //Code to show a counter with Hour, minutes, seconds and milliseconds:
            var now = new Date().getTime();
            var used = now - window.past.getTime();

            var milliseconds = used % 1000;
            var seconds = Math.floor((used / 1000) % 60);
            var minutes = Math.floor((used / (60 * 1000)) % 60);
            var hours = Math.floor((used / (60 * (60 * 1000))) % 60);

            $("#progressTimer").text(hours + ":" + minutes + ":" + seconds + "." + milliseconds);

        });
    };

    $(document).ready(function () {
        window.past = new Date();
        $("#progressLabel").text(0);
        $.updateProgress();
    });


</script>

I have to report you that this application works successfully locally hosted, it means that after choosing a file and to push the button UPLOAD, we can see immediately the TesteDownload.cshtml page and the counter working with the percent of upload growing up. When I published this application on a server that is not on my machine, the page freezes after the click and the other page appear only when the file transfer have finished.

I wish to know what is really is happen, I mean. The asynchronous method really works with an ajax on the server? Is there a difference between local host and the server which do not allows this functionality?

Since now I appreciate any little help.

[]s Léo

Community
  • 1
  • 1
LeoFraietta
  • 165
  • 3
  • 11

1 Answers1

1

I think your are mixing up some ideas here. So to answer your direct question: Yes, the $.get is real ajax and you can deep into it using browser extensions like Firebug in Firefox or the DevTools in IE. BUT: You'r not doing it the way, AJAX should be done. You have 2 loops: 1 one the client and another one on the server.

Your server-loop is not really connected to your client-loop und thus I think the result simple depends on. If you are for instance use the IISExpress in Visual Studio locally (you just hit F5) than you will experience a different behavior than on a real IIS-machine on the web.

StatusUpload is another problem because you will call it in a polling-like way and you have to deal with blocked threads here too. It really depends on 100+ other things like the application pool configuration on your server.

Solution: Keep the upload-information on the client side. See this posting for a possible alternative. The idea is, that you have one async method on server-side and measure your progress on the client.

I'm sure there are tons of javascript-alternatives to uploadify (my link) on the web.

Community
  • 1
  • 1
Alexander Schmidt
  • 4,930
  • 4
  • 33
  • 71
  • Ok, i got in my mind which there are two different loops, one in client and the other on server, my try is use the ajax on client to get the status of the uploading file on the server. But you are right, I'm not sure if I am doing this on the right way. I've read the post you suggested and I tried to use de uploadfy component, but i faced the problem that other people are facing too, "uploadify.swf?preventswfcaching=" on the newest version of this component. One thing I need to study and learn more about is the threads that you said ... – LeoFraietta Feb 20 '14 at 14:53
  • This is old but I was review my questions and it's all right i was mixing the ideas. – LeoFraietta Jan 31 '19 at 21:18