简体   繁体   中英

Asynchronous FTP upload on ASP.NET MVC4 web pages

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 , 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 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 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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM