6

i use https://github.com/promosis/file-upload-with-preview to display preview for multiple image

var upload = new FileUploadWithPreview('myUniqueUploadId', {
  maxFileCount: 4,
  text: {
    chooseFile: 'Maximum 4 Images Allowed',
    browse: 'Add More Images',
    selectedCount: 'Files Added',
  },
});
.custom-file-container {
  max-width: 400px;
  margin: 0 auto;
}
<link href="https://unpkg.com/file-upload-with-preview@4.0.2/dist/file-upload-with-preview.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/file-upload-with-preview@4.0.8/dist/file-upload-with-preview.min.js"></script>
<form action="save.php" method="post" enctype="multipart/form-data">
  <div class="custom-file-container" data-upload-id="myUniqueUploadId">
    <label>Upload File <a href="javascript:void(0)" class="custom-file-container__image-clear" title="Clear Image">&times;</a></label>
    <label class="custom-file-container__custom-file">
                    <input type="file" name="files[]" class="custom-file-container__custom-file__custom-file-input" accept="image/*" multiple aria-label="Choose File">
                    <input type="hidden" name="MAX_FILE_SIZE" value="10485760" />
                    <span class="custom-file-container__custom-file__custom-file-control"></span>
                </label>
    <div class="custom-file-container__image-preview" style="overflow: auto!important"></div>
  </div>
  <input type="submit" value="Upload Image" name="submit">
</form>

it works fine, but i can't add a extra image are remove image.

https://github.com/promosis/file-upload-with-preview/issues/30#issuecomment-563352824 enableing cachedFileArray example

Adding

i added 3 images to input, i get 3 images in preview without submitting form i added 1 image now i get 4 images in preview, When i submit the form i get only 1 image upload(recently added file).

Removing

it happens same in removing image added 4 images and removed 1 image when i upload all 4 images are uploaded, everything happen only on preview but noting happen in <input>

----Is there any other better way to do(other codes or library) But i want to use my custom upload handler.

PHP upload handler

$desired_dir = "$_SERVER[DOCUMENT_ROOT]/upload/file/";
$thumb_directory = "$_SERVER[DOCUMENT_ROOT]/upload/thumb/";
$file = [];
$nw = 125;
$nh = 90;
if (!empty($_POST)) {
    if (isset($_FILES['files'])) {
        $uploadedFiles = array();
        foreach ($_FILES['files']['tmp_name'] as $key => $tmp_name) {
            $errors = array();
            $file_name = md5(uniqid("") . time());
            $file_size = $_FILES['files']['size'][$key];
            $file_tmp = $_FILES['files']['tmp_name'][$key];
            $file_type = $_FILES['files']['type'][$key];
            if ($file_type == "image/gif") {
                $sExt = ".gif";
            } elseif ($file_type == "image/jpeg" || $file_type == "image/pjpeg") {
                $sExt = ".jpg";
            } elseif ($file_type == "image/png" || $file_type == "image/x-png") {
                $sExt = ".png";
            }
            if (!in_array($sExt, array('.gif', '.jpg', '.png'))) {
                $errors[] = "Image types alowed are (.gif, .jpg, .png) only!";
            }
            if ($file_size > 2097152000) {
                $errors[] = 'File size must be less than 2 MB';
            }


            if (empty($errors)) {
                if (is_dir($desired_dir) == false) {
                    mkdir("$desired_dir", 0700);
                }
                $file_name_with_ext = $file_name . $sExt;
                $source = $desired_dir . $file_name_with_ext ;
                if(!move_uploaded_file($file_tmp, $source)) {
                    echo "Couldn't upload file " . $_FILES['files']['tmp_name'][$key];
                    $file[] = NULL;
                }else{
                    $size = getimagesize($source);
                    $w = $size[0];
                    $h = $size[1];
                    switch ($sExt) {
                        case '.gif':
                            $simg = imagecreatefromgif($source);
                            break;
                        case '.jpg':
                            $simg = imagecreatefromjpeg($source);
                            break;
                        case '.png':
                            $simg = imagecreatefrompng($source);
                            break;
                    }
                    $dest = $thumb_directory. $file_name_with_ext ;
                    $dimg = resizePreservingAspectRatio($simg, $nw, $nh);
                    imagepng($dimg, $dest);
      // imagewebp($dimg, $dest);
                    compress($source, "$desired_dir"  . $file_name_with_ext , 50);
                    compress($dest, $dest , 50);
                    $file[] =   $file_name_with_ext ;
                }
            }else{
                // TODO: error handling
            } 
        }

    }

    $stmt = $conn->prepare("INSERT INTO allpostdata(im1, im2, im3, im4)"
            . " VALUES (:im1, :im2, :im3, :im4)");

    $stmt->bindParam(':im1', $file[0], PDO::PARAM_STR, 100);
    $stmt->bindParam(':im2', $file[1], PDO::PARAM_STR, 100);
    $stmt->bindParam(':im3', $file[2], PDO::PARAM_STR, 100);
    $stmt->bindParam(':im4', $file[3], PDO::PARAM_STR, 100);
    if ($stmt->execute()) {
        header('Location: https://google.com');
    }exit;
}

function compress($source, $destination, $quality) {
    $info = getimagesize($source);
    if ($info['mime'] == 'image/jpeg') {
        $image = imagecreatefromjpeg($source);
    } elseif ($info['mime'] == 'image/gif') {
        $image = imagecreatefromgif($source);
    } elseif ($info['mime'] == 'image/png') {
        $image = imagecreatefrompng($source);
    }
    imagejpeg($image, $destination, $quality);
    return $destination;
}

function resizePreservingAspectRatio($img, $targetWidth, $targetHeight) {
    $srcWidth = imagesx($img);
    $srcHeight = imagesy($img);
    $srcRatio = $srcWidth / $srcHeight;
    $targetRatio = $targetWidth / $targetHeight;
    if (($srcWidth <= $targetWidth) && ($srcHeight <= $targetHeight)) {
        $imgTargetWidth = $srcWidth;
        $imgTargetHeight = $srcHeight;
    } else if ($targetRatio > $srcRatio) {
        $imgTargetWidth = (int) ($targetHeight * $srcRatio);
        $imgTargetHeight = $targetHeight;
    } else {
        $imgTargetWidth = $targetWidth;
        $imgTargetHeight = (int) ($targetWidth / $srcRatio);
    }
    $targetImg = imagecreatetruecolor($targetWidth, $targetHeight);
    $targetTransparent = imagecolorallocate($targetImg, 255, 0, 255);
    imagefill($targetImg, 0, 0, $targetTransparent);
    imagecolortransparent($targetImg, $targetTransparent);
    imagecopyresampled($targetImg, $img, 0, 0, 0, 0, $targetWidth, $targetHeight, $srcWidth, $srcHeight);
    return $targetImg;
}
?>
sanoj lawrence
  • 951
  • 5
  • 29
  • 69
  • 2
    Can you show the PHP code that is handling the upload? Because that code is most likely the reason for your issue. –  Dec 05 '19 at 12:49
  • show are your PHP script – ahmednawazbutt Dec 05 '19 at 12:51
  • @ChrisG yes i even thought about that and tried with https://stackoverflow.com/a/24895361/3836908 and my custom upload script https://stackoverflow.com/a/59141067/3836908 – sanoj lawrence Dec 05 '19 at 12:51
  • @ahmednawazbutt added `php` script also tried with this code too https://stackoverflow.com/a/24895361/3836908 but nothing works – sanoj lawrence Dec 05 '19 at 12:54
  • what is the output for $_FILES array? There is a chance that you only get 1 file there – ahmednawazbutt Dec 05 '19 at 12:56
  • @ahmednawazbutt when ever i add or remove image it happen only on preview, if i remove a image it is removed form preview only while uploading that removed file is also uploaded. – sanoj lawrence Dec 05 '19 at 12:59
  • so you get all 4 images in $_FILES regardless an image is removed or not. Right? – ahmednawazbutt Dec 05 '19 at 13:02
  • There's a syntax error in your PHP: `$source = = $desired_dir . $file_name_with_ext ;` –  Dec 05 '19 at 13:02
  • @ahmednawazbutt yes your right – sanoj lawrence Dec 05 '19 at 13:04
  • buddy I think file cannot be removed since you have not asked in your Js/JQuery to remove it from input – ahmednawazbutt Dec 05 '19 at 13:06
  • @ahmednawazbutt how can i do that to `add` or `remove`. – sanoj lawrence Dec 05 '19 at 13:07
  • also about adding image, when ou add another file (second click to upload) the previous ones are overridden so you get only latest file – ahmednawazbutt Dec 05 '19 at 13:07
  • @ChrisG typo error corrected it (edited) – sanoj lawrence Dec 05 '19 at 13:09
  • I think my answer should give you clue on this – ahmednawazbutt Dec 05 '19 at 13:10
  • The library you're using supports multiple images, but in order to send them to your backend, you have to manually add `upload.cachedFileArray` to a FormData object. The library isn't supposed to be used in a `
    ` (because the input only stores the last image you've added, and submitting the form only sends that last image, regardless of previously added or removed ones)
    –  Dec 05 '19 at 13:18
  • @ChrisG so how do i add `upload.cachedFileArray` ? – sanoj lawrence Dec 05 '19 at 13:22
  • I've tried a few things and I don't think you can use this library with standard form submission. It collects the file objects, but that's all it does. I've tried multiple things, including manually generating a new `` for each file, but couldn't get it to work. Just use a different library that supports standard form submission. –  Dec 05 '19 at 13:45
  • @ChrisG can you suggest few library easy to do understand. – sanoj lawrence Dec 05 '19 at 13:49
  • No, sorry, that's your job –  Dec 05 '19 at 14:12
  • @ChrisG here is a solution, https://github.com/promosis/file-upload-with-preview/issues/30 for `upload.cachedFileArray` now how do i solve with above code. – sanoj lawrence Dec 10 '19 at 14:35

2 Answers2

3

I successfully got this to work using the method described by the author, but I'm using fetch() instead of jQuery:

document.forms[0].addEventListener("submit", async function (e) {
    e.preventDefault();
    const url = this.getAttribute("action"); // grab endpoint from HTML
    const fd = new FormData();   // create FormData object
    upload.cachedFileArray.forEach((file, i) => {
        fd.append("files[]", file); // append each file to FormData object
    });
    this.querySelectorAll("input[name], select, textarea").forEach(el => {
        fd.append(el.getAttribute("name"), el.value);
    });
    const response = await fetch(url, {
        method: 'POST',
        body: fd
    });
    // optional processing of server response
    const text = await response.text();
    console.log('Success:', text);
    // what happens after upload here
    location = "https://google.com"; // navigate to Google
});

Add this to your script. It intercepts the form submission, creates a FormData object based on the File array, adds the remaining form fields, then submits it to the url stated it the form's action attribute. Note that you should probably remove the name attribute from the <input type="file"> on the form, since we don't want to add that to the FormData.

  • it works what about `text Input` are those normal form submission??? – sanoj lawrence Dec 10 '19 at 16:32
  • @sanojlawrence Sorry, what do you mean? Which `text Input`? –  Dec 10 '19 at 17:04
  • `` i have multiple inputs are those normal form processing ? – sanoj lawrence Dec 10 '19 at 17:53
  • @sanojlawrence If you have additional inputs, you need to add their `name` and `.value` to the FormData object. The form is not sent the regular way; you have to use AJAX instead for the images, so everything has to be handled by the code I posted. –  Dec 10 '19 at 18:06
  • can it be done in jQuery so that i can send `` or how can i send data in above code – sanoj lawrence Dec 10 '19 at 19:08
  • @sanojlawrence I edited the code so it picks up all ``, ` –  Dec 10 '19 at 19:19
  • everything works fine, But even after clicking i see images are uploaded and `input` are sent but the page remains same no redirect, are refresh. – sanoj lawrence Dec 10 '19 at 20:11
  • @sanojlawrence Is your PHP script sending back a reply? Does it get logged in the console? –  Dec 10 '19 at 22:54
  • here is the console https://i.stack.imgur.com/nhyvY.png and now solved. https://stackoverflow.com/a/20035319/3836908 is that the correct solution. – sanoj lawrence Dec 11 '19 at 09:16
  • I thought that's a given but you need to remove `header('Location: https://google.com');` from your PHP script since you're no longer navigating there but requesting it via AJAX. Replace it with something like `echo count($_FILES['files']['size']) . " images uploaded";` –  Dec 11 '19 at 09:42
0

I think that you should just have to make sure to add the multiple parameter to your input like this:

input type="file" class="custom-file-container__custom-file__custom-file-input" accept="*" multiple
Watercayman
  • 7,970
  • 10
  • 31
  • 49
saadmrb
  • 1
  • 1
  • If you look at OP's code, the `multiple` attribute is already in there. –  Dec 18 '19 at 12:15