Retina images are not created when uploading through the webservice



  • This is a follow-up to this thread: Retina images help.

    Retina 2x images are NOT created either via the webservice.

    I got it fixed for csv import but we are going to maintain our products via Filemaker Pro and I also need to import images using the webservice.

    I fixed it for my use so if someone is willing to fix this in the real build it would be much appreciated.

    Fix goes into /override/webservice/WebserviceSpecificManagementImages.php.

    I did not fix the customizations part since I don’t need it. The added code is under the “// Retina 2x images” comments.

    Hopefully this helps someone else, here is the full override code:

    class WebserviceSpecificManagementImages extends WebserviceSpecificManagementImagesCore
    {
        /**
         * Write the posted image on disk
         *
         * @param string $receptionPath
         * @param int    $destWidth
         * @param int    $destHeight
         * @param array  $imageTypes
         * @param string $parentPath
         *
         * @return bool
         *
         * @throws WebserviceException
         */
        protected function writePostedImageOnDisk($receptionPath, $destWidth = null, $destHeight = null, $imageTypes = null, $parentPath = null)
        {
            $imgMaxUploadSize = Tools::getMaxUploadSize();
            
            // Retina 2x images
            $generateHiDpiImages = (bool) Configuration::get('PS_HIGHT_DPI');
            
            if ($this->wsObject->method == 'PUT') {
                if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) {
                    $file = $_FILES['image'];
                    if ($file['size'] > $imgMaxUploadSize) {
                        throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($imgMaxUploadSize / 1000)), [72, 400]);
                    }
                    // Get mime content type
                    $mimeType = false;
                    if (Tools::isCallable('finfo_open')) {
                        $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
                        $finfo = finfo_open($const);
                        $mimeType = finfo_file($finfo, $file['tmp_name']);
                        finfo_close($finfo);
                    } elseif (Tools::isCallable('mime_content_type')) {
                        $mimeType = mime_content_type($file['tmp_name']);
                    } elseif (Tools::isCallable('exec')) {
                        $mimeType = trim(exec('file -b --mime-type '.escapeshellarg($file['tmp_name'])));
                    }
                    if (empty($mimeType) || $mimeType == 'regular file') {
                        $mimeType = $file['type'];
                    }
                    if (($pos = strpos($mimeType, ';')) !== false) {
                        $mimeType = substr($mimeType, 0, $pos);
                    }
    
                    // Check mime content type
                    if (!$mimeType || !in_array($mimeType, $this->acceptedImgMimeTypes)) {
                        throw new WebserviceException('This type of image format is not recognized, allowed formats are: '.implode('", "', $this->acceptedImgMimeTypes), [73, 400]);
                    } // Check error while uploading
                    elseif ($file['error']) {
                        throw new WebserviceException('Error while uploading image. Please change your server\'s settings', [74, 400]);
                    }
    
                    // Try to copy image file to a temporary file
                    if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image']['tmp_name'], $tmpName)) {
                        throw new WebserviceException('Error while copying image to the temporary directory', [75, 400]);
                    } // Try to copy image file to the image directory
                    else {
                        $result = $this->writeImageOnDisk($tmpName, $receptionPath, $destWidth, $destHeight, $imageTypes, $parentPath);
                    }
    
                    @unlink($tmpName);
    
                    return $result;
                } else {
                    throw new WebserviceException('Please set an "image" parameter with image data for value', [76, 400]);
                }
            } elseif ($this->wsObject->method == 'POST') {
                if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) {
                    $file = $_FILES['image'];
                    if ($file['size'] > $imgMaxUploadSize) {
                        throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($imgMaxUploadSize / 1000)), [72, 400]);
                    }
                    require_once(_PS_CORE_DIR_.'/images.inc.php');
                    if ($error = ImageManager::validateUpload($file)) {
                        throw new WebserviceException('Image upload error : '.$error, [76, 400]);
                    }
    
                    if (isset($file['tmp_name']) && $file['tmp_name'] != null) {
                        if ($this->imageType == 'products') {
                            $product = new Product((int) $this->wsObject->urlSegment[2]);
                            if (!Validate::isLoadedObject($product)) {
                                throw new WebserviceException('Product '.(int) $this->wsObject->urlSegment[2].' does not exist', [76, 400]);
                            }
                            $image = new Image();
                            $image->id_product = (int) ($product->id);
                            $image->position = Image::getHighestPosition($product->id) + 1;
    
                            if (!Image::getCover((int) $product->id)) {
                                $image->cover = 1;
                            } else {
                                $image->cover = 0;
                            }
    
                            if (!$image->add()) {
                                throw new WebserviceException('Error while creating image', [76, 400]);
                            }
                            if (!Validate::isLoadedObject($product)) {
                                throw new WebserviceException('Product '.(int) $this->wsObject->urlSegment[2].' does not exist', [76, 400]);
                            }
                            Hook::exec('updateProduct', ['id_product' => (int) $this->wsObject->urlSegment[2]]);
                        }
    
                        // copy image
                        if (!isset($file['tmp_name'])) {
                            return false;
                        }
                        if ($error = ImageManager::validateUpload($file, $imgMaxUploadSize)) {
                            throw new WebserviceException('Bad image : '.$error, [76, 400]);
                        }
    
                        if ($this->imageType == 'products') {
                            $image = new Image($image->id);
                            if (!(Configuration::get('PS_OLD_FILESYSTEM') && file_exists(_PS_PROD_IMG_DIR_.$product->id.'-'.$image->id.'.jpg'))) {
                                $image->createImgFolder();
                            }
    
                            if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmpName)) {
                                throw new WebserviceException('An error occurred during the image upload', [76, 400]);
                            } elseif (!ImageManager::resize($tmpName, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format)) {
                                throw new WebserviceException('An error occurred while copying image', [76, 400]);
                            } else {
                                $imagesTypes = ImageType::getImagesTypes('products');
                                foreach ($imagesTypes as $imageType) {
                                    if (!ImageManager::resize($tmpName, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'-'.stripslashes($imageType['name']).'.'.$image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) {
                                        $this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']);
                                    }
                                    
                                    // Retina 2x images
                                    if ($generateHiDpiImages) {
                                    	if (!ImageManager::resize($tmpName, _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'-'.stripslashes($imageType['name']).'2x.'.$image->image_format, (int) $imageType['width'] * 2, (int) $imageType['height'] * 2, $image->image_format)) {
                                    				$this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']).'2x';
                                    	}
                                    }
                                }
                            }
                            @unlink($tmpName);
                            $this->imgToDisplay = _PS_PROD_IMG_DIR_.$image->getExistingImgPath().'.'.$image->image_format;
                            $this->objOutput->setFieldsToDisplay('full');
                            $this->output = $this->objOutput->renderEntity($image, 1);
                            $imageContent = ['sqlId' => 'content', 'value' => base64_encode(file_get_contents($this->imgToDisplay)), 'encode' => 'base64'];
                            $this->output .= $this->objOutput->objectRender->renderField($imageContent);
                        } elseif (in_array($this->imageType, ['categories', 'manufacturers', 'suppliers', 'stores'])) {
                            if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmpName)) {
                                throw new WebserviceException('An error occurred during the image upload', [76, 400]);
                            } elseif (!ImageManager::resize($tmpName, $receptionPath)) {
                                throw new WebserviceException('An error occurred while copying image', [76, 400]);
                            }
                            $imagesTypes = ImageType::getImagesTypes($this->imageType);
                            foreach ($imagesTypes as $imageType) {
                                if (!ImageManager::resize($tmpName, $parentPath.$this->wsObject->urlSegment[2].'-'.stripslashes($imageType['name']).'.jpg', $imageType['width'], $imageType['height'])) {
                                    $this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']);
                                }
                                
                                // Retina 2x images
                                if ($generateHiDpiImages) {
                                	if (!ImageManager::resize($tmpName, $parentPath.$this->wsObject->urlSegment[2].'-'.stripslashes($imageType['name']).'2.jpg', (int) $imageType['width'] * 2, (int) $imageType['height'] * 2)) {
                                		$this->_errors[] = Tools::displayError('An error occurred while copying image:').' '.stripslashes($imageType['name']).'2x';
                                	}
                                }
                            }
                            @unlink(_PS_TMP_IMG_DIR_.$tmpName);
                            $this->imgToDisplay = $receptionPath;
                        } elseif ($this->imageType == 'customizations') {
                            $filename = md5(uniqid(rand(), true));
                            $this->imgToDisplay = _PS_UPLOAD_DIR_.$filename;
                            if (!($tmpName = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmpName)) {
                                throw new WebserviceException('An error occurred during the image upload', [76, 400]);
                            } elseif (!ImageManager::resize($tmpName, $this->imgToDisplay)) {
                                throw new WebserviceException('An error occurred while copying image', [76, 400]);
                            }
                            $productPictureWidth = (int) Configuration::get('PS_PRODUCT_PICTURE_WIDTH');
                            $productPictureHeight = (int) Configuration::get('PS_PRODUCT_PICTURE_HEIGHT');
                            if (!ImageManager::resize($this->imgToDisplay, $this->imgToDisplay.'_small', $productPictureWidth, $productPictureHeight)) {
                                throw new WebserviceException('An error occurred while resizing image', [76, 400]);
                            }
                            @unlink(_PS_TMP_IMG_DIR_.$tmpName);
    
                            $query = 'INSERT INTO `'._DB_PREFIX_.'customized_data` (`id_customization`, `type`, `index`, `value`)
    							VALUES ('.(int) $this->wsObject->urlSegment[3].', 0, '.(int) $this->wsObject->urlSegment[4].', \''.$filename.'\')';
    
                            if (!Db::getInstance()->execute($query)) {
                                return false;
                            }
                        }
    
                        return true;
                    }
                }
            } else {
                throw new WebserviceException('Method '.$this->wsObject->method.' is not allowed for an image resource', [77, 405]);
            }
        }
    }
    


  • Hello,
    as you have written in the previous thread it seems it is not working in TB 1.0.3 ? Is this still unsolved?

    Well looks like I will have to look into the webservice code after all.
    Just upgraded to 1.0.3 and the retina images are not created via the webservice image upload either.
    Will report what I find.

    It is also very interesting for me, as we use JTL Wawi to upload images and i think it will need this also and to the changes as you do. thank you



  • It was not solved in 1.0.3 so I did this fix today in mine.

    EdIt: I did not check if the fix for csv upload was done in 1.0.3 cause I did fix it in mine anyway… I may have misunderstood your question.



  • OK thank you. How can i check it the retina pics will be generated?

    Our theme will support retina pics (as written in the theme description), but not sure about TB in combination with our upload by “JTL Wawi” (this is kind of a ERP software).

    Found also this, have we to use this also? http://imulus.github.io/retinajs/



  • @DRMasterChief if your theme supports retina images that code is unnecessary but I saw many themes which advertise they support retina images and they don’t. Actually there are quite few which really do…



  • @mockob said in Retina images are not created when uploading through the webservice:

    @DRMasterChief if your theme supports retina images that code is unnecessary but I saw many themes which advertise they support retina images and they don’t. Actually there are quite few which really do…

    Actually there is more…

    Even if your theme supports Retina, the csv import and image creation through the webservice DOES NOT create them. It’s only working when you add them through the backend.

    Also I would suggest to use the great ImageMagick v1.3.0 - by Michael Dekker & Robert Andersson module. It allows you to keep the original uploaded image UNMODIFIED on the server.

    Keep the original copy on the server. By default thirty bees encodes the image immediately after uploading and twice when resizing. By enabling this option, encoding right after the upload will be disabled.

    You also have to make sure that you have the option to create high resolution image set to ON in the back office (see picture, sorry for the french language).

    0_1504099035524_Capture d’écran 2017-08-30 à 09.15.17.png


  • administrators

    We are going to merge your code into thirty bees, making sure this’ll be easier for you in future versions. Thank you for the suggestion to improve it!



  • @mdekker said in Retina images are not created when uploading through the webservice:

    We are going to merge your code into thirty bees, making sure this’ll be easier for you in future versions. Thank you for the suggestion to improve it!

    My pleasure :relaxed:


Log in to reply
 

Looks like your connection to thirty bees forum was lost, please wait while we try to reconnect.