Change uploaded root folder name Dropzone.js
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

I'm using Dropzone.js and PHP to upload a folder that contains files and sub folders. Everything uploads correctly. However, I need to rename the root folder to a random string based on the current timestamp on upload. All the folders within the root folder need to keep their original names.

I've been able to change the names of the root folder and all the sub folders, but I can't figure out how to change the name of just the root folder leaving the original sub folder names. The code that handles the moving, and saving of the files is listed below.

<?php 
    //upload.php 
    $ds = DIRECTORY_SEPARATOR;
    $storeFolder = 'uploads/';
    $rand = substr(md5(time()),0,8);

    if (!empty($_FILES)) {

        $tempFile = $_FILES['file']['tmp_name'];

        $targetPath = dirname( __FILE__ ) . $ds . $storeFolder . $ds;

        $fullPath = $storeFolder.rtrim($_POST['path'], "/.");

        $folder = substr($fullPath, 0, strrpos($fullPath, "/"));

        if (!is_dir($folder)) {
            $old = umask(0);
            mkdir($folder, 0777, true);
            umask($old);
        }    

        if (move_uploaded_file($tempFile, $fullPath)) {
            die($fullPath);
        } else {
            die('e');
        }
    } 
?>

This is the HTML/Javascript inside the the upload page that call the upload.php code listed above. The only other thing I'm loading besides the latest version of Dropzone.js is jQuery.

<!DOCTYPE html>
    <head>
        <meta charset="UTF-8">
        <title>Folder uploader, keeping recursive directory structure</title>
        <link href="css/dropzone.css" type="text/css" rel="stylesheet" />
    </head>
    <body>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script>window.jQuery || document.write('<script src="assets/js/vendor/jquery-1.9.1.min.js"><\/script>')</script>

        <script src="js/dropzone.js"></script>

        <form action="upload.php" class="dropzone" id="uploadFile" name="uploadFile" method="POST">
            <span id="tmp-path"></span>
        </form>


        <script>
            $(document).ready(function () {
                Dropzone.autoDiscover = false;

                Dropzone.options.uploadFile = {
                  init: function() {
                    this.on("success", function(file, responseText) {
                      file.previewTemplate.appendChild(document.createTextNode(responseText));
                    });

                    this.on("sending", function(file) {
                        $("#tmp-path").html('<input type="hidden" name="path" value="'+file.fullPath+'" />')
                    });            
                  }
                }; 

                var myDropzone = new Dropzone("#uploadFile", { 
                    url: "upload.php"
                });               

            });
        </script>

    </body>
</html>
Hey, can you please update the post with the HTML code? i can't implement myself dropzone for some reason.
enderdba 27 days ago
Just added the code from the index.php file.
imokyourok 27 days ago
By the way, you are using strrpos() instead of strpos(), for this reason, the random values are applied to all the subfolders.
cueball 27 days ago
I tried using strpos() instead of strrpos() and that stopped the files being saved to the server.
imokyourok 27 days ago
Yes, because then the if(!is_dir($folder)) statement would fail and the files cannot be copied to the correct location. You should replace the first directory segment with the modified version for each upload and/or POST data received by the script and check that full directory tree. And then you can write the file. But, each upload is independent, and here comes the other issue: the script will compute a new random value for each upload, so if the root folder is test you will get test_rand_111/, test_rand_123/a/, test_rand_321/a/file.jpg, test_rand_... and so on, for each subfolder and file in the queue. Splitting everything into multiple destinations. Do you have a specific reason to use this approach? Apart avoiding overwrites.
cueball 27 days ago
awarded to enderdba

Crowdsource coding tasks.

4 Solutions


Just replace the upload.php file with the following version:

<?php 
    //upload.php 
    $ds = DIRECTORY_SEPARATOR;
    $storeFolder = 'uploads/';
    $rand = substr(md5(time()),0,8);

    if (!empty($_FILES)) {

        $tempFile = $_FILES['file']['tmp_name'];

        $targetPath = dirname( __FILE__ ) . $ds . $storeFolder . $ds;

        $fullPath = $storeFolder.rtrim($_POST['path'], "/.");
        //-- Randomize Root Folder --//
        $rootFolder = explode( "/", $_POST['path'] );
        $rootFolder = $rootFolder[0];
        $fullPath = preg_replace('/' . $rootFolder . '/', $rand, $fullPath, 1);
        //-- Randomize Root Folder --//

        $folder = substr($fullPath, 0, strrpos($fullPath, "/"));

        if (!is_dir($folder)) {
            $old = umask(0);
            mkdir($folder, 0777, true);
            umask($old);
        }    

        if (move_uploaded_file($tempFile, $fullPath)) {
            die($fullPath);
        } else {
            die('e');
        }
    } 
?>
Your's is the closest, but still not working. Your version split the contents into two randomly name folders. https://s3-us-west-2.amazonaws.com/s.cdpn.io/1932025/uploads-3.jpeg You can see the image of what it's supposed to look like and what your solution did upon upload https://s3-us-west-2.amazonaws.com/s.cdpn.io/1932025/uploads-2.jpeg
imokyourok 27 days ago
Strange. I get a different result with only one random folder created.
kostasx 27 days ago
What version of Dropzone.js are you using?
kostasx 27 days ago
The latest, just downloaded from Dropzone.js today.
imokyourok 27 days ago
Winning solution

UPDATED

Since Dropzone just makes a lot of requests (1 upload per file) when a folder is uploaded, you need to set only 1 md5 value for all uploads.. In this javascript i change that:

$(document).ready(function () {
        Dropzone.autoDiscover = false;
        $("#uploadFile").attr("class","dropzone");
        Dropzone.options.uploadFile = {
          init: function() {
            this.on("success", function(file, responseText) {
              file.previewTemplate.appendChild(document.createTextNode(responseText));
            });

            this.on("sending", function(file) {
                if(typeof file.fullPath != "undefined"){
                var changePath = file.fullPath.split("/");
                changePath[0] = md5(new Date());
                changePath = changePath.join("/");
                $("form").append('<input type="hidden" name="path" value="'+changePath+'" />')
            }
            });            
          }
        }; 

        var myDropzone = new Dropzone("#uploadFile", { 
            url: "index.php"
        });               

    });

Try this, remember to import the md5.js script in your HTML so you can use the MD5 hash in Javascript:
By default, javascript can't do md5 hashes, but with this script you can do. Add the CDN to your HTML file and it should work.

<script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.10.0/js/md5.js"></script>

Tried your code and it didn't work. Nothing was uploaded and saved to the server.
imokyourok 27 days ago
I updated the solution, it can't be Server side because the Date can change and upload various files and folders. It needs to be only one randomly named folder for all the uploads, so it only appends all the structure you need to the directory.
enderdba 27 days ago
Looks like this solution may be working. I need to try it in other browsers first. I'll update once I'm done testing.
imokyourok 27 days ago
I tried it on Microsoft Edge and it doesn't seem to be working. It worked on all major browsers on macOS. I'll see if I can get another Microsoft device to try it on.
imokyourok 27 days ago
It works on all browsers they way I need to to. Thanks.
imokyourok 27 days ago

<?php
$ds = DIRECTORY_SEPARATOR;
$storeFolder = 'uploads/';
$rand = substr(md5(time()),0,8);

if (!empty($_FILES)) {
  $tempFile = $_FILES['file']['tmp_name'];

  $targetPath = dirname( __FILE__ ) . $ds . $storeFolder . $ds;

  $fullPath = $storeFolder.rtrim($_POST['path'], "/.");

  $folder = $storeFolder . $rand . substr(substr($fullPath, 8), strpos(substr($fullPath, 8), "/"));

  if (!is_dir($folder)) {
    $old = umask(0);
    mkdir($folder, 0777, true);
    umask($old);
  }

  $newFullPath = $folder . substr($_POST['path'], strrpos($_POST['path'], "/"), strlen($_POST['path'])-1);

  if (move_uploaded_file($tempFile, $newFullPath)) {
    die($fullPath);
  } else {
    die('e');
  }
}
?>
It doesn't need to be server side. However, it can only rename the root folder, not sub folders. For example projectname>img>image.jpg should be changed to randomname>img>image.jpg I don't know enough Javascript to do what you are suggesting to the paramName
imokyourok 27 days ago
I tested it preliminarily and it seemed to work fine. All you have to do is add paramName: new Date().toString(), in your existing javascript code right before your init: function() line (line 5). See my second code example in my solution.
jduplessis294 27 days ago
I just tried the code you supplied, it didn't change any folder names, and it deleted the files withing the folders. Do I need to change anything in the dropzone.js file?
imokyourok 27 days ago
Also, where do I put the following code snippet? Dropzone.options.myAwesomeDropzone = {...};
imokyourok 27 days ago
Disregard that code. I cannot get your PHP server to run to test the issue you are getting, so I am having trouble diagnosing your error. Sorry. If you can't get the javascript to work, you could also do it in the PHP in the move_uploaded_file call by appending $rand to where you want to move the file.
jduplessis294 27 days ago
I tried using $rand to append to the folder names, and it works, but it appends the root folder and the sub folders. I only want it to append the root folder and leave the sub folders unchanged.
imokyourok 27 days ago
I have diagnosed your problem. Am working on a new solution.
jduplessis294 27 days ago
I changed my solution to fix the php. Once again could not get the formatting correct. Please let me know if there is any issues.
jduplessis294 27 days ago
Keep your old Javascript
jduplessis294 27 days ago
I just tried the new solution and it's not working. I now creating two uploads, one appended, one original. Here is a link to a screenshot of how it's splitting up the files and folders. https://s3-us-west-2.amazonaws.com/s.cdpn.io/1932025/uploads.jpeg What I'm ultimately looking for is the name of the root folder changed to a random name, and the contents of the folder untouched. Here is an example of the file structure I want. https://s3-us-west-2.amazonaws.com/s.cdpn.io/1932025/uploads-2.jpeg
imokyourok 27 days ago
Updated to working code. Fits description of what you want I believe.
jduplessis294 27 days ago
Your update didn't work, it deleted files, made new folders, etc. https://s3-us-west-2.amazonaws.com/s.cdpn.io/1932025/uploads-4.jpeg
imokyourok 27 days ago

Hello, the set of files I made and tested is:
uploadForm.html:
`<!DOCTYPE html>


Folder uploader, keeping recursive directory structure




window.jQuery || document.write('')

    <script src="js/dropzone.js"></script>

    <form action=upload.php" class="dropzone" id="uploadFile" name="uploadFile" method="POST">
        <span id="tmp-path"></span>
    </form>


    <script>
        var mddate;
        $(document).ready(function () {
            Dropzone.autoDiscover = false;

            Dropzone.options.uploadFile = {
              init: function() {
                this.on("success", function(file, responseText) {
                  file.previewTemplate.appendChild(document.createTextNode(responseText));
                });

                this.on("sending", function(file) {
                    $("#tmp-path").html('<input type="hidden" name="path" value="'+mddate+"/"+file.fullPath+'" />')
                });            
              }
            }; 
            var ondrop=function(event){
                    mddate=md5(new Date()).substr(0,8);
            }
            var myDropzone = new Dropzone("#uploadFile", { 
                url: "upload.php", drop:ondrop
            });               

        });
    </script>

</body>


The PHP file upload.php is:
<?php
header("Content-Type: text/html");
he
ader("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");
header("Vary: Origin");
$ds = DIRECTORY_SEPARATOR;
$storeFolder = 'uploaded';
if (!is_dir($storeFolder)) {
$old = umask(0);
mkdir($storeFolder, 0777, true);
umask($old);
}
foreach ($_FILES as $file=>$filestruct) {
$tempFile = $filestruct['tmp_name'];

$targetPath1 = dirname( __FILE__ ) . $ds .$storeFolder . $ds;
$targetFile = $targetPath1.rtrim($_POST['path'], "/.");
$targetDir=dirname( $targetFile );

true));

if (!is_dir($targetDir)) {
    $old = umask(0);
    mkdir($targetDir, 0777, true);
    umask($old);
}    

if (move_uploaded_file($tempFile, $targetFile)) {
    //die("Successful obtaining $targetFile file from $tempFile");
} else {
    die("Error in obtaining $targetFile file from $tempFile");
}

}
?>`
The headers set in the PHP file were needed in my server to avoud obtaining errors, you can test if in your case are necessary.
Best regards.
Lucio Montero.

View Timeline