简体   繁体   中英

Image Upload Javascript PHP - How to keep original filename?

I'm trying to build-in an Image Uplaoder to my CMS for the gallery. I've done some research and found what I need to build it. The uploader uses three files. The first one is where to select the images for upload and showing some progress. Connected to this is a js file for resizing the selected images first and upload them afterwards. And last but not least a file to process the images on server via php and for writing data into sql-database.

The good point is: Everything works as it should. BUT I have a problem with sorting the images. Because they are getting a md5 generated filename, and the uploader handles multiple images at a time, some images that I took for example at the end of a day are showed first and the first pictures of the day are for example anywhere between them.

So here comes my question: Is there a way to keep the orignal filename and name the uploaded image for example anything like "1234md5randomdigits_ORIGINALFILENAME.jpg"?

I've tried a lot of $_FILES and other php parameters, but they were empty...

Here is my upload file for selecting images:

<!DOCTYPE html>
    <html>
        <head>
            <title>multiple.php</title>
            <link rel="stylesheet" href="./style.css" />
        <head>
        <body>

            <h1>Upload Images...</h1>

            <form>
                <input type="file" multiple />
                <div class="photos">

                </div>
            </form>

            <script src="./upload.js"></script>
        </body>
    </html>

Here comes the upload.js file

// Once files have been selected
document.querySelector('form input[type=file]').addEventListener('change', function(event){

    // Read files
    var files = event.target.files;

    // Iterate through files
    for (var i = 0; i < files.length; i++) {

        // Ensure it's an image
        if (files[i].type.match(/image.*/)) {

            // Load image
            var reader = new FileReader();
            reader.onload = function (readerEvent) {
                var image = new Image();
                image.onload = function (imageEvent) {

                    // Add elemnt to page
                    var imageElement = document.createElement('div');
                    imageElement.classList.add('uploading');
                    imageElement.innerHTML = '<span class="progress"><span></span></span>';
                    var progressElement = imageElement.querySelector('span.progress span');
                    progressElement.style.width = 0;
                    document.querySelector('form div.photos').appendChild(imageElement);

                    // Resize image
                    var canvas = document.createElement('canvas'),
                        max_size = 1200,
                        width = image.width,
                        height = image.height;
                    if (width > height) {
                        if (width > max_size) {
                            height *= max_size / width;
                            width = max_size;
                        }
                    } else {
                        if (height > max_size) {
                            width *= max_size / height;
                            height = max_size;
                        }
                    }
                    canvas.width = width;
                    canvas.height = height;
                    canvas.getContext('2d').drawImage(image, 0, 0, width, height);

                    // Upload image
                    var xhr = new XMLHttpRequest();
                    if (xhr.upload) {

                        // Update progress
                        xhr.upload.addEventListener('progress', function(event) {
                            var percent = parseInt(event.loaded / event.total * 100);
                            progressElement.style.width = percent+'%';
                        }, false);

                        // File uploaded / failed
                        xhr.onreadystatechange = function(event) {
                            if (xhr.readyState == 4) {
                                if (xhr.status == 200) {

                                    imageElement.classList.remove('uploading');
                                    imageElement.classList.add('uploaded');
                                    imageElement.style.backgroundImage = 'url('+xhr.responseText+')';

                                    console.log('Image uploaded: '+xhr.responseText);

                                } else {
                                    imageElement.parentNode.removeChild(imageElement);
                                }
                            }
                        }

                        // Start upload
                        xhr.open('post', 'process.php', true);
                        xhr.send(canvas.toDataURL('image/jpeg'));

                    }

                }

                image.src = readerEvent.target.result;

            }
            reader.readAsDataURL(files[i]);
        }

    }

    // Clear files
    event.target.value = '';

});

And this my "process.php" to process the uploaded data:

<?php
$save_path="/images";
// Generate filename
$filename = md5(mt_rand()).".jpg";

// Read RAW data
$data = file_get_contents("php://input");

// Read string as an image file
$image = file_get_contents("data://".substr($data, 5));

// Save to disk
if ( ! file_put_contents($save_path.$filename, $image)) {
    exit();
}

// Clean up memory
unset($data);
unset($image);

//Includes and SQL go after that

// Return file URL
echo $save_path.$filename;
?>

I'd be very happy about some help! :)

This is what I use to process potentially any number of upload files if you leave the file name as it is here it will leave it the same as the users file name. Make your form element name an array and it will loop through it uploading all the files. You'll also have to set your form type to multipart. This should be a lot easier to manage than what it looks like you're trying to do though.

    $target_dir = "images/";
    extract($_POST);
    $error=array();
    $extension=array("jpg", "gif");
    $i=0;
    foreach($_FILES["filetoupload"]["tmp_name"] as $key=>$tmp_name) {
        $file_name = $_FILES["filetoupload"]["name"][$key];
        $ext = strtolower(pathinfo($file_name,PATHINFO_EXTENSION));
        $file_tmp=$_FILES["filetoupload"]["tmp_name"][$key];
        if(in_array($ext,$extension))   {
            if ($_FILES["filetoupload"]["size"][$key] < 5000000) {
                if ($_FILES["filetoupload"]["size"][$key] != 0) {
                    if(!file_exists( $target_dir . $file_name ))  {
                        move_uploaded_file($file_tmp , $target_dir . $file_name );
                    }
                }
            }
        } else {
            array_push($error,"$file_name, ");
        }
    }

in this example the name attribute of all of the file input fields is name="filetoupload[]"

In support of my comment above if you send a custom header in the ajax function you can process that server side. I think I got the syntax right for accessing the filename from the files collection

/* ajax: add custom header */
xhr.open('post', 'process.php', true);
xhr.setRequestHeader( 'filename', files[i].name );
xhr.send(canvas.toDataURL('image/jpeg'));


/* php: resort to original md5 name if header failed  */
$filename=!empty( $_SERVER['HTTP_FILENAME'] ) ? $_SERVER['HTTP_FILENAME'] : md5(mt_rand()).".jpg";

As I originally forgot to add HTTP_ to the beginning of the custom header ( php ) it initially would not have worked - a simple oversight on my behalf. To correct that I put together a quick demo of using the custom headers idea from end to end, though the code that follows does not entirely emulate your original code with the image processing, canvas, FileReader etc it does show the important aspect of assigning the custom request header and how to process that server-side in php so I hope it will give you an idea how you can implement the original filename feature.

<?php
    /* 
        emulate server side processing of uploaded file - 
        here it simply sends back the custom headers and
        a single POST variable but this would be processing
        the image data and saving the file  
    */
    if( $_SERVER['REQUEST_METHOD']=='POST' ){
        ob_clean();

        $filename = !empty( $_SERVER['HTTP_FILENAME'] ) ? $_SERVER['HTTP_FILENAME'] : md5( mt_rand() ).".jpg";
        $filetype = !empty( $_SERVER['HTTP_FILETYPE'] ) ? $_SERVER['HTTP_FILETYPE'] : 'M.I.A';
        $filesize = !empty( $_SERVER['HTTP_FILESIZE'] ) ? $_SERVER['HTTP_FILESIZE'] : 'M.I.A';

        $action   = !empty( $_POST['action'] ) ? $_POST['action'] : 'M.I.A';

        /* send proper content type response header */
        header( 'Content-Type: application/json' );

        /* add some custom response headers to show how you can pass headers and process them */
        header( sprintf( 'Uploaded-Filename: %s', $filename ) );
        header( sprintf( 'Uploaded-Filesize: %s', $filesize ) );
        header( sprintf( 'Uploaded-Filetype: %s', $filetype ) );

        /* send payload back to ajax callback */
        exit( json_encode( array(
            'filename'  =>  $filename,
            'filesize'  =>  $filesize,
            'filetype'  =>  $filetype,
            'action'    =>  $action
        )));
    }
?>
<!doctype html>
<html>
    <head>
        <title>ajax custom headers</title>
        <style>
            body,body *{
                font-family:calibri,verdana,arial;
                font-size:0.9rem;
            }
        </style>
        <script>
            function bindEvents(){
                /* DOM elements */
                var oDiv=document.getElementById('results');
                var oPre=document.getElementById('headers');
                var oBttn=document.getElementById('bttn');
                var oFile=document.querySelector('form input[type="file"]');


                /* basic callback function to show response */
                var callback=function(r,h){
                    oDiv.innerHTML=r;
                    oPre.innerHTML=h;
                }

                oBttn.onclick=function(){
                    /* as there is only a single file we know the index is zero */
                    var oCol=oFile.files;
                    var file=oCol.item(0).name;
                    var size=oCol.item(0).size;
                    var type=oCol.item(0).type;


                    /* ultra basic ajax request with custom request headers */
                    var xhr=new XMLHttpRequest();
                    xhr.onreadystatechange=function(){
                        if( this.readyState==4 && this.status==200 ){
                            /*
                                The callback can take whatever arguments we want - here simply
                                the response and some headers - could easily process specific
                                response headers rather than all
                            */
                            callback.call( this, this.response, this.getAllResponseHeaders() );
                        }
                    };
                    xhr.open( 'POST', location.href, true );
                    xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
                    /* add custom request headers - original file details */
                    xhr.setRequestHeader( 'filename', file );
                    xhr.setRequestHeader( 'filetype', type );
                    xhr.setRequestHeader( 'filesize', size );

                    xhr.send( 'action=headers-test' );                  
                }
            }

            document.addEventListener( 'DOMContentLoaded', bindEvents, false );
        </script>
    </head>
    <body>
        <div id='results'></div>
        <pre id='headers'></pre>
        <form method='post'>
            <input type='file' />
            <input type='button' id='bttn' value='Send Ajax Request with custom headers' />
        </form>
    </body>
</html>

Following on from your comment regarding multiple files all sharing the same name hopefully the following might help.

<form method='post'>
    <input type='file' multiple=true />
    <input type='button' id='bttn' value='Send Ajax Request with custom headers' />
    <div class='photos'></div>
</form>


<script>

    document.querySelector( 'form input[type="file"]' ).addEventListener( 'change', function( event ){

        // Read files
        var files = event.target.files;

        // Iterate through files
        for( var i = 0; i < files.length; i++ ) {

            // Ensure it's an image
            if ( files[i].type.match( /image.*/ ) ) {


                // Load image
                var reader = new FileReader();
                    /* 
                        assign custom properties to the reader 
                        object which will allow you to access 
                        them within callbacks 
                    */
                    reader.filename=files[i].name;
                    reader.filesize=files[i].size;
                    reader.filetype=files[i].type;

                reader.onload = function( readerEvent ) {


                    /*
                        assign each new image with the properties from the reader
                        - these will be available within the ajax function so you
                        can set the custom headers
                    */
                    var image = new Image();
                        image.filename=this.filename;
                        image.filesize=this.filesize;
                        image.filetype=this.filetype;

                    image.onload = function( imageEvent ) {

                        console.log('image onload - - - > > > > > %s -> %s',this.filename,this.filesize);


                        // Add element to page
                        var imageElement = document.createElement('div');
                            imageElement.classList.add('uploading');
                            imageElement.innerHTML = '<span class="progress"><span></span></span>';

                        var progressElement = imageElement.querySelector('span.progress span');
                            progressElement.style.width = 0;

                        document.querySelector('form div.photos').appendChild( imageElement );

                        // Resize image
                        var canvas = document.createElement('canvas'),
                            max_size = 1200,
                            width = image.width,
                            height = image.height;
                        if ( width > height ) {
                            if( width > max_size ) {
                                height *= max_size / width;
                                width = max_size;
                            }
                        } else {
                            if( height > max_size ) {
                                width *= max_size / height;
                                height = max_size;
                            }
                        }
                        canvas.width = width;
                        canvas.height = height;
                        canvas.getContext('2d').drawImage( image, 0, 0, width, height );

                        // Upload image
                        var xhr = new XMLHttpRequest();
                        if( xhr.upload ) {


                            xhr.upload.addEventListener('progress', function(event) {
                                var percent = parseInt( event.loaded / event.total * 100 );
                                progressElement.style.width = percent+'%';
                            }, false);


                            xhr.onreadystatechange = function(event) {
                                if( xhr.readyState == 4 ) {
                                    if( xhr.status == 200 ) {

                                        imageElement.classList.remove('uploading');
                                        imageElement.classList.add('uploaded');
                                        imageElement.style.backgroundImage = 'url('+xhr.responseText+')';

                                    } else {
                                        imageElement.parentNode.removeChild( imageElement );
                                    }
                                }
                            }
                            xhr.open( 'post', location.href, true ); //'process.php'
                            xhr.setRequestHeader( 'filename', image.filename );
                            xhr.setRequestHeader( 'filetype', image.filetype );
                            xhr.setRequestHeader( 'filesize', image.filesize );
                            xhr.send( canvas.toDataURL('image/jpeg') );
                        }
                    };
                    image.src = readerEvent.target.result;
                };
                reader.readAsDataURL( files[i] );
            }
        }
        // Clear files
        event.target.value = '';
    });
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM