ARTLUNG LAB Share
 
drop image (or click)

HTML

    <div class="filedrag" style="width: 500px;">
        <label class="filedrag-filename"></label>
        <img class="filedrag-preview" src="img/placeholder.gif">
        <div>&nbsp;</div>
        <div class="filedrag-droparea">drop image (or click)</div>
        <div class="filedrag-progress"></div>
        <input type="file" class="filedrag-input" id="file-input" name="file-input">
    </div>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

JavaScript

// Based on https://www.sitepoint.com/html5-ajax-file-upload/ (but heavily modified)

var MAX_FILE_SIZE = 33554432; //32MB

function parseFile(file, image_target, callback) {
    //Basic file type validation
    if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {
        alert('Invalid image type. Valid formats: jpg, gif, png');
        return false;
    }

    //File size validation
    if (file.size > MAX_FILE_SIZE) {
        alert('File is too large. Max file size: ' + MAX_FILE_SIZE);
        return false;
    }

    //Toss an image preview in there right from the client-side
    var reader = new FileReader();
    reader.onload = function (e) {
        image_target.siblings('.filedrag-preview').attr('src', e.target.result);
        image_target.siblings('filedrag-filename').html(file.name);
    }
    reader.readAsDataURL(file);

    window[callback];
}

function uploadFile(file, post_target, input_id, onComplete) {
    var xhr = new XMLHttpRequest();
    var response = null;

    //Create progress bar
    $(".filedrag-progress").html('<p>Uploading...</p>');

    //Update progress bar
    xhr.upload.addEventListener("progress", function (e) {
        var pc = parseInt(100 - (e.loaded / e.total * 100));
        $(".filedrag-progress p").css("backgroundPosition", pc + "% 0");
    }, false);

    //Upload finished
    xhr.onreadystatechange = function (e) {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                $(".filedrag-progress p")
                    .addClass("success")
                    .html("Success!")
                    .fadeOut('slow', function () {
                        $(".filedrag-progress p")
                            .html("")
                            .removeClass("success");
                    });

                if (!xhr.responseText) {
                    $('.filedrag-filename').html('Error fetching post response');
                    return false;
                }

                response = JSON.parse(xhr.responseText);
                response.input_id = input_id;

                if (onComplete) {
                    window[onComplete](response);
                }
            } else {
                $('.filedrag-filename').html('Error posting image');
                return false;
            }
        }
    };

    //Start the upload
    xhr.open("POST", post_target + "/filetype/" + file.type.replace("image/", ""), true);
    xhr.setRequestHeader("X-FILENAME", file.name);
    xhr.send(file);
}

function initUploaders(post_target, onComplete) {
    var xhr = new XMLHttpRequest();

    //Only do this stuff if the technology is supported
    if (xhr.upload) {

        var dropArea = $('.filedrag-droparea');
        var dragAreaInput = $('.filedrag-input');

        //Handle the dragover event
        dropArea.on("dragover", function (e) {
            e.stopPropagation();
            e.preventDefault();
            if (!$(this).hasClass('hover')) {
                $(this).addClass('hover');
            }
        });

        //And the dragleave event
        dropArea.on("dragleave", function (e) {
            e.stopPropagation();
            e.preventDefault();
            if ($(this).hasClass('hover')) {
                $(this).removeClass('hover');
            }
        });

        //A file was dragged onto the droppable area, do stuff
        dropArea.on("drop", function (e) {
            //Prevent bubbling or default browser handling of image drag/drop
            e.stopPropagation();
            e.preventDefault();

            //Disable hover state
            if ($(this).hasClass('hover')) {
                $(this).removeClass('hover');
            }

            //Fetch the images from the FileList object
            var files = e.originalEvent.dataTransfer.files;

            //We'll return this in the response, because it comes in handy sometimes
            var input_id = $(this).siblings('.filedrag-input').attr('id');

            // process all File objects
            for (var i = 0, f; f = files[i]; i++) {
                parseFile(f, $(this));
                uploadFile(f, post_target, input_id, onComplete);
            }
        });

        dropArea.on("click", function (e) {
            $(this).siblings('.filedrag-input').trigger('click');
        });

        //Handle file select
        dragAreaInput.change(function (e) {
            var files = e.target.files;

            //We'll return this in the response, because it comes in handy sometimes
            var input_id = $(this).siblings('.filedrag-input').attr('id');

            // process all File objects
            for (var i = 0, f; f = files[i]; i++) {
                parseFile(f, $(this));
                uploadFile(f, post_target, input_id, onComplete);
            }
        });

        //Show the drag and drop area
        dropArea.show();
        dragAreaInput.hide();
    }
}

function responseCallback(response) {
    console.log(response);
}

$(function () {
    initUploaders('accept-input.php', 'responseCallback');
});

SCSS

.filedrag-droparea {
  display: none;
  font-weight: bold;
  text-align: center;
  padding: 1em 0;
  margin: 1em 0;
  color: #555;
  border: 2px dashed #555;
  border-radius: 7px;
  cursor: default;
}

.filedrag-droparea.hover {
  color: #f00;
  border-color: #f00;
  border-style: solid;
  box-shadow: inset 0 3px 4px #888;
}

.filedrag-preview {
  max-width: 100%;
}

.filedrag-progress p {
  display: block;
  width: 240px;
  padding: 2px 5px;
  margin: 2px 0;
  border: 1px inset #446;
  border-radius: 5px;
  background: #eee url(img/progress.png) 100% 0 repeat-y;
}

.filedrag-progress p.success {
  background: #0c0 none 0 0 no-repeat;
}

.filedrag-progress p.failed {
  background: #c00 none 0 0 no-repeat;
}

PHP: accept-input.php


<?php

$fn 
= ($_SERVER['HTTP_X_FILENAME'] ?? false);

$types = array('image/png''image/jpeg''image/gif');
$extensions = array('png''jpg''gif');
$maxsize 1024 1024// 1MB


$okToUpload false;

/**
 * We will respond with json with a key of input_id if successful
 *
 * @param $input_id
 * @param $message
 *
 * @return void
 */
function respondAndExit($input_id$message)
{
    echo 
json_encode(
        array(
            
'input_id' => $input_id,
            
'message' => $message
        
)
    );
    exit();
}

if (
$fn) :

    if (
in_array($_SERVER['CONTENT_TYPE'], $types)
        && 
in_array(pathinfo($fnPATHINFO_EXTENSION), $extensions)
        && 
$_SERVER['CONTENT_LENGTH'] <= $maxsize
    
) {

        
file_put_contents(
            
'uploads/' $fn,
            
file_get_contents('php://input')
        );
        
//        echo "$fn uploaded";
        
respondAndExit('fileselect'"$fn uploaded");

    } else {
        
respondAndExit('fileselect'"Invalid file");
    }


else:

    
// form submit
    
$files $_FILES['fileselect'];

    foreach (
$files['error'] as $id => $err) {
        if (
$err == UPLOAD_ERR_OK) {
            
$fn $files['name'][$id];
            
move_uploaded_file(
                
$files['tmp_name'][$id],
                
'uploads/' $fn
            
);

        }
    }
    
respondAndExit('fileselect'"File uploaded");

endif;