Search code examples
formsimageclipboardimagedata

How do I accept file uploads from pasting a file into the browser?


Accepting image uploads from a paste into the browser window is much easier than traditional file upload form inputs and even the newer style drag 'n' drop file uploads.

How do I implement it?


Solution

  • Here's an example PHP/JavaScript page that accepts drag 'n' drop image uploads. It's not dependent on PHP though - you could adapt it quite easily to work with another server-based language. This code was based on a snippet I found on jsFiddle by someone called Nick.

    This is a full page - so you should be able to copy the code below and put it in a file on your web-server as-is (if you're not running PHP then you'll need to update the PHP code at the top or point the form to your own form handler script).

    <?php
        if (!empty($_POST)) {
            
            // Handle the POSTed data here - the image is actually base64 encoded data in
            // the $_POST['myTextarea'] variable which you can run through the base64_decode()
            // function and then write to a file
            
            $pos     = strpos($_POST['myTextarea'], 'base64,');
            $encoded = substr($_POST['myTextarea'], $pos + 7);
            $raw     = base64_decode($encoded);
    
            // Show the base64 encoded $data - use the $raw variable when writing to a file
            var_dump($_POST);
            exit;
        }
    ?>
    <!DOCTYPE html >
    <html>
    <body>
    
    <h1>File upload using paste</h1>
    
    <p>
        You can paste an image, which is on your clipboard, into this window and it will appear below.
        If you use Windows you can press <b>PrtScr</b> to get a screenshot on your clipboard. Then
        press <b>CTRL+V</b> to paste it into this document.
    </p>
    
    <!-- PUT THE ADDRESS OF YOUR FORM HANDLER SCRIPT IN THE ACTION ATTRIBUTE -->
    <form action="" method="post">
        <div id="form-elements-container">
            <input type="text" value="An example text input..." name="myTextInput"><br />
            <input type="submit" value="Submit form"><br />
        </div>
    </form>
    
    <!-- THIS IS WHERE THE IMAGE THUMBNAILS WILL APPEAR -->
    <div id="images-container"></div>
    
    <script>
        counter = 0;
    
        document.body.onpaste = function (e)
        {
            // use event.originalEvent.clipboard for newer chrome versions
            var items = (e.clipboardData  || e.originalEvent.clipboardData).items;
    
            // Find pasted image among pasted items
            var blob = null;
            for (var i=0; i<items.length; i++) {
                if (items[i].type.indexOf("image") === 0) {
                    blob = items[i].getAsFile();
                }
            }
    
            // Load image if there is a pasted image
            if (blob !== null) {
                
                var reader = new FileReader();
                
                reader.onload = function(e)
                {
                    // Create a new image object from the pasted data
                    var img    = new Image();
                    img.src    = e.target.result;
                    img.width  = 128;
                    img.height = 128;
                    img.style.margin = '5px';
                    
                    // Append the file to the document
                    document.getElementById('images-container').appendChild(img);
                    
                    // Add a new textarea to the form
                    var textarea    = document.createElement('textarea');
                    textarea.name   = 'myTextarea_' + counter++;
                    textarea.value  = img.src;
                    textarea.style.width  = '200px';
                    textarea.style.height = '200px';
                    document.getElementById('form-elements-container').appendChild(textarea);
                    
                };
        
                reader.readAsDataURL(blob);
            }
        }
    </script>
    </body>
    </html>