Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a smart remote upload script with jQuery AJAX and PHP

I'm currently creating an image hosting script and so far so good. I've used several plugins to create the local uploading process with drag & drog + AJAX which works totally fine. Now I've moved to the part where I need to create the remote uploading process with jQuery AJAX and a PHP script to handle the whole thing.

How it's gonna work

My thought are like this: There is a big box in the middle of the page that accepts the URLs to be remote uploaded. Once valid URL(s) are passed into the text area, they will be immediately sent to the server side script via jQuery AJAX. It's bound with a keyup event.

This is how it looks like: http://i.imgur.com/NhkLKii.png.
The "HERE COME THE URLS" part is already a text area - So that part's already done.


Where I need help

The issue with this whole situation is: Once there are valid URLs pasted into the text area, those must be immediately be converted to some sort of box which also includes an uploading progress. Something that looks like this (copied from the local uploading part): http://i.imgur.com/q7RyDmb.png

It was easy implement the progress indicator for the local uploading, since it was a feature offered by the plugin I've used, but I don't know how to indicate the progress of remote uploading, which is totally being made from scratch.

So this is how I've imagined the logic to flow:

  1. User pastes some URLs into the text area
  2. There is a client-side check to validate the pasted URLs
  3. Validated URLs are send to upload.php on keyup (?)
  4. URLs are being processed
  5. While the upload goes on, we show the users the progress in the knob (?)
  6. PHP script finishes the process and returns back the uploaded URLs
  7. I update the page in the AJAX success callback to display the uploaded files

So, the two process flows marked with (?) are unclear to me - I don't know how to achieve those...


What I have tried

Well, I didn't just come here and ask you to do everything for me, but I've come across a dead end and I don't know how to continue. What I've done so far is collect the URLs from the text area, and if there are multiple URLs separated by a line break (\n), I simply use split to get an array of pasted text and then use another function inside the loop to validate if they are URLs. If there is no line break detected inside the text area value, then I simply check the one line that was provided. On each case, I send the whole text area to the PHP script, because I don't know how to get rid of the invalid URLs in jQuery. I've created a function called debug() in PHP which stores anything into a debug.log file and this is what I'm getting (in one try) when I paste something into the text area:

https://www.google.com/https://www.google.com/

I paste https://www.google.com/ once in the text area, but it gets logged twice in the PHP side and I can't determine why.

This is how my jQuery looks like:

// Remote upload
    var char_start  = 10;
    var index       = 0;
    var urls        = $('.remote-area');
    var val_ary     = [];

    urls.keyup(function(){      
        if (urls.val().length >= char_start)
        {           
            var has_lbrs = /\r|\n/i.test(urls.val());
            val_ary = urls.val().split('\n');

            if (has_lbrs)
            {
                for (var i = 0; i < val_ary.length; i++)
                {
                    if (!validate_url(val_ary[i]))
                    {
                        val_ary.splice(i, 1);
                        continue;   
                    }       
                }

                $.ajax({
                    type: 'POST',
                    url: 'upload.php',
                    data: {
                        upload_type: 'remote', // Used to determine the upload type in PHP
                        urls: val_ary, // Sending the whole array here
                    },
                });
            }
            else
            {
                if (!validate_url(urls.val()))
                {
                    // Display an error here
                    return; 
                }

                $.ajax({
                    type: 'POST',
                    url: 'upload.php',
                    data: {
                        upload_type: 'remote', // Used to determine the upload type in PHP
                        urls: urls.val(), // Sending what's in the text area
                    },
                });
            }
        }
    });

The questions

So the final questions are:

  • How do I send my information correctly to the PHP script, only valid URLs and have them kind of "process-able" in my PHP script.
  • How do I indicate the progress of the upload?

If I was somewhere unclear during my question, please let me know, I'll try to reexplain.

Thank you.


Updates

09/12/2013

I think I have managed to solve the double-sending issue where my AJAX would send the same information twice to the PHP script. What I did was code in a delay anonymous function that sends the text area content to the PHP script after an user stops typing for 2 seconds. Once the user stops typing again, the timer resets and a new AJAX request will be made. So, I'm assuming that this issue has been solved. I'll come back to it if anything strange occurs.

Now I'm still left with the progress indicators part. I'd appreciate your thoughts on that one.

My new code: http://pastebin.com/SaFSLeE9

like image 517
aborted Avatar asked Dec 08 '13 13:12

aborted


People also ask

How can save Ajax file in jQuery?

ajax({ url: 'my url', type: 'POST', data: formData, success: function (response) { if (response) { // Do whatever you want to do with response } }, error: function (error) { console. log(error) }, cache: false, contentType: false, processData: false }); return false; });


1 Answers

What you're looking for in terms of communicating progress back and forth is "pushing". That refers to the technique of server sending data to the client, rather than the other way around, which is the standard HTTP way of doing things.

You've got plenty of options available, as described in the explanatory Wikipedia article, though perhaps more relevant to this topic would be Comet. What happens is you trigger and $.ajax call just like the one you have now, but you set a very long timeout. That essentially gives the server a "channel" to send data back to the page whenever it's available.

So what you need is a .php on the server that is capable of handling long polling and will send data back to the page as the upload progress changes (probably in array form for multiple uploads). This article should get you started with some jQuery code. Just remember that this request doesn't go to upload.php. This request goes to a different script that deals solely with upload percentages and only returns data when that is available, it doesn't return immediately as all others scripts - the Ajax will happily wait for the data.

Also, don't separate your code like that with has_lbrs. One line or many are not distinct cases, one line is just an edge case of many lines. You're duplicating the code unnecessarily. What does the else case do that would break in the general case? Further, the "error handling" in the else case is misleading. The only error reporting you do is if there is only one line and it's wrong. What if you have two lines and they're both wrong? Your code will happily send an empty array to upload.php.

This is why I think you shouldn't separate your code like that, because then you'll split logic and not even notice it.

like image 104
Naltharial Avatar answered Nov 09 '22 04:11

Naltharial