Alan Alan - 4 months ago 9
MySQL Question

Upload files to user folder

I'm trying to create a new folder within the upload folder so that a user can upload file to there own folder.
Can I do this using PHP or do I need to a column "LONGBLOB" in MYSQL?
I've read that it's not good practice to store images in you database

<?php
header('Content-Type: application/json');

$succeeded = [];
$failed =[];
$uploaded = [];
$allowed = ['png', 'gif', 'jpg'];

if(!empty($_FILES["file"])) {

foreach ($_FILES['file']['name'] as $key => $name) {
if ($_FILES['file']['error'][$key] === 0) {

$temp = $_FILES['file']['tmp_name'][$key];

$ext = explode('.', $name);

$ext = strtolower(end($ext));

$file = md5_file($temp) . time() . '.' . $ext;

if (in_array($ext, $allowed) === true && move_uploaded_file($temp, "uploads/{$file}") === true) {
$succeeded[] = array(
'name' => $name,
'file' => $file
);

}else{
$failed[] = array(
'name' => $name);
}
}
}


}

if (!empty($_POST['ajax'])) {
echo json_encode(array(
'succeeded' => $succeeded,
'failed' => $failed ));
}



?>

Answer

Assuming you have the user's username or id in a session variable then that could be used as the basis for the new folder into which he/she would upload files. Obiously that same username,id would have to be used when they wish to download the file. By storing a hash and the filepath you can generate links that do not reveal filename, folder path, owner etc as the db could check the ash and return the file and path when needed.

The following is an untested example of generating the user's own folder and using that in the upload process - hope it gives you some ideas / guidance.

<?php


    $succeeded = [];
    $failed =[];
    $uploaded = [];
    $allowed = ['png', 'gif', 'jpg'];


    /*
        generate a suitable name for the new folder, 
        remove characters which might be troublesome
    */
    $userdir = str_replace( 
        array("'",'"','-'),
        array('','','_'),
        $_SESSION['username']
    );



    /* 
        new path into which the files are saved
        It might be better to have the files 
        stored outside of the document root.
    */
    $savepath = 'uploads/' . $userdir;



    /* create the folder if it does not exist */
    if( !file_exists( $savepath ) ) {
        mkdir( $savepath );
        chown( $savepath, $username );
        chmod( $savepath, 0644 );
    }



    if( !empty( $_FILES["file"] ) ) {

        foreach( $_FILES['file']['name'] as $key => $name ) {
            if( $_FILES['file']['error'][$key] === 0 ) {

                $temp = $_FILES['file']['tmp_name'][$key];

                /*
                    is there anything to be gained by hashing the filename?
                    the hash would be the same for filenames with the same 
                    name anyway.

                    If the file is large, calculating the hash of the file could
                    take some time...
                */
                $ext = explode('.', $name);
                $ext = strtolower( end( $ext ) );
                $file = md5_file( $temp ) . time() . '.' . $ext;


                /* generate a random hash to use in downloads */
                $hash=uniqid( md5( date(DATE_COOKIE) ) ); 


                /* here probably - store reference in db? Assign permissions based upon owner etc */
                $sql='insert into `table` (`filename`,`username`,`uid`,`datetime`,`hash`) values (?,?,?,?,?);';             

                /* bind params and execute - not shown */



                if ( in_array( $ext, $allowed ) === true && move_uploaded_file( $temp, "{$savepath}/{$file}") === true ) {
                    $succeeded[] = array( 'name' => $name, 'file' => $file );
                }else{
                    $failed[] = array( 'name' => $name );
                }
            }
        }
    }

    if (!empty($_POST['ajax'])) {

        header('Content-Type: application/json');
        echo json_encode(array(
            'succeeded' => $succeeded,
            'failed' => $failed ));
    } else {

        header( 'HTTP/1.1 404 Not Found', true, 404 );
    }
?>