PrestaShop: allow customers to upload PDF, AI and EPS files as product customization

Issue

I am running Prestashop 1.6.1.7 and I have the following pictureUpload() method that allows users to upload files of their choosing. By default Prestashop allows uploads of GIF, JPG, JPEG or PNG only.

I’m trying to allow users the ability to upload a few more types (pdf, ai and eps specifically)

Here is the pictureUpload() method in the productController override:

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));
            $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;
}

This is looking to the ImageManager class, which has this method (that I have updated the error message on):

public static function validateUpload($file, $max_file_size = 0, $types = null)
{

    if ((int)$max_file_size > 0 && $file['size'] > (int)$max_file_size) {
        return sprintf(Tools::displayError('Image is too large (%1$d kB). Maximum allowed: %2$d kB'), $file['size'] / 1024, $max_file_size / 1024);
    }
    if (!ImageManager::isRealImage($file['tmp_name'], $file['type']) || !ImageManager::isCorrectImageFileExt($file['name'], $types) || preg_match('/\%00/', $file['name'])) {
        return Tools::displayError('Image format not recognized, allowed formats are: .gif, .jpg, .png, .pdf, .ai, .eps'); //I Updated This - this is the error kicking off when I try to upload AI
    }
    if ($file['error']) {
        return sprintf(Tools::displayError('Error while uploading image; please change your server\'s settings. (Error code: %s)'), $file['error']);
    }
    return false;
}

The place where that method fails is pointing to two additional methods posted below. I updated the isRealImage method to try and allow the types I wanted through, but it still fails (and I commented where it fails).

public static function isRealImage($filename, $file_mime_type = null, $mime_type_list = null)
{
    // Detect mime content type
    $mime_type = false;
    if (!$mime_type_list) {
        //I UPDATED THIS LIST TO ALLOW FOR OTHER FILETYPES
        $mime_type_list = array('image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png', 'application/illustrator', 'application/ai', 'application/eps', 'application/x-eps', 'image/eps', 'image/x-eps', 'application/pdf', 'application/acrobat', 'application/x-pdf', 'text/pdf', 'text/x-pdf');
    }

    // Try 4 different methods to determine the mime type

    if (function_exists('getimagesize')) {
        $image_info = @getimagesize($filename);
        //HERE IMAGE_INFO IS SHOWING AS 'FALSE' SO IT GOES NO FURTHER WHEN UPLOADING A .AI FILE
        if ($image_info) {
            $mime_type = $image_info['mime'];
        } else {
            $file_mime_type = false;
        }
    } elseif (function_exists('finfo_open')) {
        $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
        $finfo = finfo_open($const);
        $mime_type = finfo_file($finfo, $filename);
        finfo_close($finfo);
    } elseif (function_exists('mime_content_type')) {
        $mime_type = mime_content_type($filename);
    } elseif (function_exists('exec')) {
        $mime_type = trim(exec('file -b --mime-type '.escapeshellarg($filename)));
        if (!$mime_type) {
            $mime_type = trim(exec('file --mime '.escapeshellarg($filename)));
        }
        if (!$mime_type) {
            $mime_type = trim(exec('file -bi '.escapeshellarg($filename)));
        }
    }

    if ($file_mime_type && (empty($mime_type) || $mime_type == 'regular file' || $mime_type == 'text/plain')) {
        $mime_type = $file_mime_type;
    }

    // For each allowed MIME type, we are looking for it inside the current MIME type
    foreach ($mime_type_list as $type) {
        if (strstr($mime_type, $type)) {
            return true;
        }
    }

    return false;
}

I also updated the isCorrectImageFileExt method:

public static function isCorrectImageFileExt($filename, $authorized_extensions = null)
{
    // Filter on file extension
    if ($authorized_extensions === null) {
        //ADDED ALLOWED TYPES I WANT
        $authorized_extensions = array('gif', 'jpg', 'jpeg', 'jpe', 'png', 'pdf', 'ai', 'eps');
    }
    $name_explode = explode('.', $filename);
    if (count($name_explode) >= 2) {
        $current_extension = strtolower($name_explode[count($name_explode) - 1]);
        if (!in_array($current_extension, $authorized_extensions)) {
            return false;
        }
    } else {
        return false;
    }

    return true;
}

Thoughts on this?

Help on this?

Solution

You have gone too deep :). This is the pictureUpload method of ProductController that I’ve already made, you don’t need others overrides. With my override you can upload pdf, ai, cdr and eps, but obviously you can change with your needs.

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));

            // Bad check, but rapid
            $extension = substr($file['name'], -3, 3);
            if($extension == 'jpg' OR $extension == 'gif' OR $extension == 'png'){
                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);
            } elseif ($extension == 'pdf' OR $extension == '.ai' OR $extension == 'cdr' OR $extension == 'eps') {
                $file_name = $file_name.'.'.str_replace('.', '', $extension);
                if (!move_uploaded_file($file['tmp_name'], _PS_UPLOAD_DIR_.$file_name)) {
                    return false;
                }
                chmod(_PS_UPLOAD_DIR_.$file_name, 0777);
                $this->context->cart->addPictureToProduct($this->product->id, $indexes[$field_name], Product::CUSTOMIZE_FILE, $file_name);
            } else {
                $this->errors[] = Tools::displayError('This format is not accepted');
            }
        }
    }
    return true;
}

After that you have to customize product.tpl, the cart summary of your template, and the backoffice order detail 🙂

Answered By – marsaldev

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published