Hanny Hanny - 2 months ago 5
PHP Question

PrestaShop: Keep the files name and extension when uploading a product customization (or at least the extension)

I am working with prestashop and allowing users to upload their own files when adding a product to their cart.

I've enabled it on the backend and on the front end I've followed this tutorial to get it setup.

Here is the block of code that handles the ajax calls and uploading of the files. I'd like it to keep the original name and extension of the file the user gave it when it uploads.

Is that possible?

var files = new Array();
$('.customizationUploadLine').find('input[type="file"]').on('change', prepareUpload);
// Grab the files and set them to our variable
function prepareUpload(event)
{
files.push({'name' : event.target.name, 'file' :event.target.files[0]});
}



function previewFile(target, file) {

$('#uniform-'+target.attr('id')).before($('<img id="preview-'+target.attr('id')+'"/>'));
var preview = $('#preview-'+target.attr('id'));
var reader = new FileReader();

preview.attr('width', 64);

reader.onloadend = function () {
preview.attr('src', reader.result);
}

if (file) {
reader.readAsDataURL(file);
} else {
preview.attr('src', "");
}
}


$('#uploadTrigger').click(function(e) {


if(files.length > 0)
{

$('<div class="myoverlay"></div>').css({

'position' : 'fixed',
'top' : 0,
'left' : 0,
'background' : 'black',
'background' : 'rgba(0,0,0,.5)',
'z-index' : 5999,
'width' : '100%',
'height' : '100%',
'cursor' : 'pointer'
}).appendTo('body');

$('<div class="uploadingfiles">Your files are being uploaded...<img src="'+baseUri+'themes/default-bootstrap/img/ajax-loader.gif"></div>')
.css({
'position' : 'absolute',
'top' : '30%',
'left' : '50%',
'width' : '300px',
'margin-left' : '-150px',
'text-align' : 'center',
'padding' : '10px',
'background' : 'white'
})
.appendTo('.myoverlay');


var data = new FormData();

$.each(files, function(key, obj)
{
data.append(obj.name, obj.file);
});

data.append('submitCustomizedDatas', 1);
data.append('ajax', 1);
$.ajax({
url: $('#customizationForm').attr('action'),
type: 'POST',
data: data,
cache: false,
dataType: 'json',
processData: false,
contentType: false,
success: function(data, textStatus, jqXHR)
{
if(typeof data.errors === 'undefined')
{
$.each(files, function(key, obj)
{
$('input[name="'+obj.name+'"]').addClass('filled');
previewFile($('input[name="'+obj.name+'"]'), obj.file);

});
$('.uploadingfiles').text('Upload Complete!');
}
else
{
$('.uploadingfiles').text('Error while uploading, please refresh the page and try again');
}
$('.myoverlay').click(function(){$(this).remove()});
},
error: function(jqXHR, textStatus, errorThrown)
{
$('.uploadingfiles').text('ERRORS: ' + errorThrown);
$('.myoverlay').click(function(){$(this).remove()});
}
});

} // end checking files length
else alert('Nothing to upload!');
});


Currently the file uploads into the uploads directory (great!) but it has a really funky name with no extension tied to it. I'd like the image to keep the name and extension so I can pass that information to the checkout screen and display their uploaded image there.

Answer

It's possible, but I don't suggest to do it. However you have to make an override of ProductController, and specifically of pictureUpload() method.

Create a new file in prestashop/overidde/controllers/front/ named ProductController.php with content writed below:

class ProductController extends ProductControllerCore {

    protected function pictureUpload()
    {
        if (!$field_ids = $this->product->getCustomizationFieldIds()) {
            return false;
        }
        $authorized_file_fields = array();
        foreach ($field_ids as $field_id) {
            if ($field_id['type'] == Product::CUSTOMIZE_FILE) {
                $authorized_file_fields[(int)$field_id['id_customization_field']] = 'file'.(int)$field_id['id_customization_field'];
            }
        }
        $indexes = array_flip($authorized_file_fields);

        foreach ($_FILES as $field_name => $file) {
            if (in_array($field_name, $authorized_file_fields) && isset($file['tmp_name']) && !empty($file['tmp_name'])) {
                // $file_name = md5(uniqid(rand(), true));// Change this
                $file_name = $file['name']; // In this
                if ($error = ImageManager::validateUpload($file, (int)Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE'))) {
                    $this->errors[] = $error;
                }

                $product_picture_width = (int)Configuration::get('PS_PRODUCT_PICTURE_WIDTH');
                $product_picture_height = (int)Configuration::get('PS_PRODUCT_PICTURE_HEIGHT');
                $tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS');
                if ($error || (!$tmp_name || !move_uploaded_file($file['tmp_name'], $tmp_name))) {
                    return false;
                }
                /* Original file */
                if (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name)) {
                    $this->errors[] = Tools::displayError('An error occurred during the image upload process.');
                }
                /* A smaller one */
                elseif (!ImageManager::resize($tmp_name, _PS_UPLOAD_DIR_.$file_name.'_small', $product_picture_width, $product_picture_height)) {
                    $this->errors[] = Tools::displayError('An error occurred during the image upload process.');
                } elseif (!chmod(_PS_UPLOAD_DIR_.$file_name, 0777) || !chmod(_PS_UPLOAD_DIR_.$file_name.'_small', 0777)) {
                    $this->errors[] = Tools::displayError('An error occurred during the image upload process.');
                } else {
                    $this->context->cart->addPictureToProduct($this->product->id, $indexes[$field_name], Product::CUSTOMIZE_FILE, $file_name);
                }
                unlink($tmp_name);
            }
        }
        return true;
    }
}

Now the uploaded file have the same name. Remember to delete class_index.php in prestashop/cache/

If you need the extension I guess that now it's more easy to do :)

Comments