Manipulace s obrázky [Nový ImageStorage]

před 2 lety

CZechBoY
Člen | 3347
+
0
-

@JanMikeš Nebude to spíš problém pojmenování? Furt si můžu udělat konkrétní aliasy CommentUserIcon a vím o co jde.
To, že někde budou miniatury je jasný už skoro od počátku projektu (pokud se obrázek dá nějak uživatelsky nahrát) takže alias vytvoříš hned.

Editoval CZechBoY (1. 2. 2017 1:00)

před 2 lety

Martk
Člen | 487
+
0
-

@JanMikeš Napadlo mě udělat parametrizované aliasy, aby se zamezilo duplicitě.

images:
    local:
        aliases:
            resizeExact: "resize:$1,$2"
{img "image.jpg", "resizeExact:150,150"}

Originální cesta je original/image.jpg
A nejspíše by se vytvořila tato cesta resizeExact/150.150/image.jpg

Tady by mohl nastat velký nepořádek v případě mnohonásobných namespace, řešením by bylo mít jen jedno namespace nebo převést namespace1/namespace2 na složku namespace1.namespace2 a nebo si dávat pozor na název aliasů a namespace.

Aliasy chci zachovat, protože u složitějších funkcí, zvláště u cloudinary a jejich vnořených funkcí, je velmi těžké generovat správný název složky.

Editoval Martk (1. 2. 2017 12:47)

před 2 lety

mordare
Začátečník | 115
+
0
-

Zdravím mám pár dotazů.

Při použití makra {img} se mi nevykreslí obrázek, ale vždy se vypíše jen cesta k němu. např.:
Při zápisu

{img 'namespace/'.$presenter->getUser()->getId().'/logo.jpg'}

se do stránky vykreslí jen text: data/namespace/1505/original/logo.jpg

Při použití attributu n:img se obrázek vykreslí, ale zaboha nemůžu přijít na to jak tam dostat helpery. Když sem postupoval podle návodu na GITu s přidáním noImage Dostanu chybovou hlášku:

syntax error, unexpected ':'

V šabloně mám

<img n:img="'namespace/'.$presenter->getUser()->getId().'/logo.jpg'|noImage:'noimage.jpg'">

Osobně bych radši používal Makro než atribut n:img. Jak to teda zprovoznit? Případně jak aspoň zprovoznit ty Helpery při použití atributu?

Jak v presenteru smazat obrázek. Přez použitou Traitu TPresenter, která zpřístupňuje ImageFacede se mi to nepovedlo. Rozjel sem to následujícím způsobem, ale nepřijde mi že by to bylo uplně správně:

$this->storage->delete($this->storage->createResource('namespace/'.$this->getUser()->getId().'/'.$photo));

ps.: verzi používám @dev

Editoval mordare (8. 2. 2017 10:00)

před 2 lety

Jan Mikeš
Člen | 773
+
0
-

@mordare makro {img} ti nevytvoří tag <img> „pouze“ vypíše tu cestu, což sám popisuješ, správně tedy je:

<img src="{img ...}">

Ps. pokud by makro vykreslovalo i tag <img>, bylo by to pak nepoužitelné například pro styles="background: url({img ...})"

Editoval Jan Mikeš (8. 2. 2017 13:36)

před 2 lety

mordare
Začátečník | 115
+
0
-

@Martk Zdravím nepřemýšlels o přidání podpory pro S3? Případně nějaké rozšíření aby si mohl každý dopsat svůj Storage? Díval sem se že teď to máš jen na pevno Local a Cloudinary.

před 2 lety

Martk
Člen | 487
+
0
-

@mordare Přemýšlel jsem spíše, jestli mám v tomto balíčku podporovat i jiné úložiště než lokální. Pokud používáš nejnovější verzi, tak tam není nic na pevno. Stačí si vytvořit novou třídu a tu podědit od WebChemistry\Images\Storage.

Základní šablona asi tady:

<?php

namespace WebChemistry\Images\Storages;

use WebChemistry\Images\Modifiers\ModifierContainer;
use WebChemistry\Images\Resources\IFileResource;
use WebChemistry\Images\Resources\IResource;
use WebChemistry\Images\Resources\Transfer\ITransferResource;
use WebChemistry\Images\Storage;
use WebChemistry\Images\Storages\Cloudinary\CloudinaryFacade;

class CloudinaryStorage extends Storage {

    private $modifierContainer;

    public function __construct(ModifierContainer $modifierContainer, array $config) {
        $this->modifierContainer = $modifierContainer;
    }

    public function link(IFileResource $resource) {
        // vsude budes potrebovat asi tohle
        $resource->getId(); // identifikator obrazku
        $resource->getAlises(); // pole aliasu
        $this->modifierContainer->modifiersFromResource($resource); // ktere modifikace po nas uzivatel chce, extrahovany z aliasu
    }

    public function save(IResource $resource) {
        if (!$resource instanceof ITransferResource) {
            return $resource; // or throw exception?
        }
        $resource->setSaved();


        return; // Vratit IFileResource
    }

    public function copy(IFileResource $src, IFileResource $dest) {

    }

    public function move(IFileResource $src, IFileResource $dest) {

    }

    public function delete(IFileResource $resource) {

    }

}

Předpokládám, že všechny změny probíhají na externím serveru, jinak by to bylo o něco málo složitější.

před 2 lety

mordare
Začátečník | 115
+
+1
-

Jo našel sem Interface a díval sem se že by to neblo ani těžké vytvořit.

Ale potom když sem se díval do DI extension soboru, který se stará o načtení konfigurace z Neonu a zaregistrování služeb tak tam to máš vytvořeno načtení konfigu jen pro Local a Cloudinary napevno. Tudíž pokud bych si napsal svůj storage tak bych si musel psát i vlastní DI. Vím že to neni problém a bylo by to v podstatě zkopírování tvého souboru s dopsáním vlastní sekce. Ale právě to mi přijde jako zbytečnost abych kopíroval něco co už je jen kvůli tomu abych tam dopsal pár řádků.

před 2 lety

Martk
Člen | 487
+
0
-

Jo to by neměl být problém dodělat, máš-li čas můžeš se klidně postarat o pr :)

před 2 lety

mordare
Začátečník | 115
+
0
-

Jo zkusím příští týden dát něco dohromady.

před 2 lety

Ivorius
Člen | 111
+
0
-

<img n:img="'image.jpg'|noImage:'noimage.jpg'">mi vyhazuje parse error na dvojtečku. Neví někdo jak to nastavit?

před 2 lety

Martk
Člen | 487
+
0
-

@Ivorius Nyní se to nastavuje v aliasech, bohužel se na to vytváří speciální složka, kterou ještě opravím.

images:
    local:
        aliases:
            article_default: 'defaultImage:noimage.jpg'
<img n:img="'image.jpg', article_default">

Editoval Martk (28. 8. 2017 7:57)

před rokem

Ivorius
Člen | 111
+
0
-

Pokud to použiji s doctrine entitou, vrací mi WebChemistry\Images\Resources\FileResource což nechce vzít n:img. Je nějaká jiná cesta než to zapsat jako

<img n:img="$user->image->getName(),mini">

před rokem

Martk
Člen | 487
+
0
-

@Ivorius díky za report, nevím proč, ale vždy mi to procházelo i s FileResource. V dev je fix.

před rokem

Rudolf247
Člen | 29
+
0
-

Zdravím, já už vážně nevím jak dál.
S uploadem jsem neměl sebemenší problém, ale při vykreslování stále dostávám hlášku „Namespace is not valid.“
Tak jsem si na basePresentru jeden obrázek přes $this->storage->createResource() dumpnul a vážně nemá přidělený žádný namespace (namespace ⇒ null).

Ale když si udělám dump po uploadu, tak obrázek namespace přidělený má.

Upload mám řešený přes jzechy/jQuery-FileUpload

public function save(\Nette\Http\FileUpload $file, array $params = []) {
    $resource = $this->storage->createUploadResource($file);
    $resource->setNamespace($params['namespace']);
    $result = $this->storage->save($resource);
    return $file->getSanitizedName();
}

Na šabloně potom

<img class="img img-fluid" src="{img 'ds/original/22467334-1984457505212953-7025201851310817024-o.jpg'}">

Děkuji za každou radu.

před rokem

Martk
Člen | 487
+
0
-

Díky za report.

Špatně bude pravděpodobně řádek:

$resource->setNamespace($params['namespace']);

Namespace může obsahovat pouze tyto znaky / a-z A-Z _ 0–9

V šabloně by mělo stačit tohle:

<img class="img img-fluid" src="{img 'ds/22467334-1984457505212953-7025201851310817024-o.jpg'}">

original se použije sám, pokud nedáš jako 2 parametr alias.


Správný upload a vykreslení by měl vypadat takhle:

$result = $this->storage->save($resource);
$idToSave = (string) $result;

$db->updateRow(['image' => $idToSave]); // aktualizace řádku v databázi

a vykreslení v šabloně:

<img src="{img $idToSave}"> {* $idToSave = vytažení obrázku z databáze *}

před rokem

Ivorius
Člen | 111
+
0
-

Martk napsal(a):

@Ivorius Nyní se to nastavuje v aliasech, bohužel se na to vytváří speciální složka, kterou ještě opravím.

images:
  local:
      aliases:
          article_default: 'defaultImage:noimage.jpg'
<img n:img="'image.jpg', article_default">

Mohl bys mi prosím ukázat, jak to tedy má vypadat, když chci zmenšené obrázky – mini a zároveň použít defaultní obrázek, pokud není nastaven?

aliases:
    user_default: "defaultImage: noimage.jpg"
    mini: "resize:30,30,exact|sharpen"
    small: "resize:120,120,exact|sharpen"
<img n:img="'image.jpg', user_default,mini">

asi není to správné

před rokem

flamengo
Člen | 124
+
0
-

Ahoj, rád bych zkusil novou verzi a tak bych se rád zeptal, jak mám použít v komponentě. Vlastně stejný dotaz, jako tento https://forum.nette.org/…imagestorage?p=3.
Zkusil jsme místo WebChemistry\Images\AbstractStorage použít WebChemistry\Images\Template\ImageFacade, ale potom mi to v latte hází Notice Undefined variable: _imageFacade.
Za odpověď předem díky.

před rokem

Ivorius
Člen | 111
+
0
-

@flamengo Musíš si to předat do šablony. Např. $this->template->_imageFacade = $this->imageFacade;

před rokem

Ivorius
Člen | 111
+
0
-

Proč je getResourceLocation private – v LocalStorage? Dá se nějak jinak získat path k resource? Potřeboval bych to na získání rozměrů obrázku, protože nikde jsem tuto funkci nenašel.

před rokem

Martk
Člen | 487
+
0
-

Protože externí úložiště jako Cloudinary nebo S3 nemůžou mít resourceLocation. Přidal jsem do všech úložišť metodu getImageSize, která vrací objekt ImageSize.

před rokem

Martk
Člen | 487
+
0
-

@flamengo V nejnovější verzi po smazání cache už není potřeba přidávat nic do šablony ani používat traitu TPresenter

@Ivorius Tvůj kód by měl v nejnovější verzi fungovat

<img n:img="'image.jpg', user_default,mini">

Nyní lze používat proměnné v aliasech:

aliases:
    resize: 'resize:$1,$2,$3'
    resizeExact: 'resize:$1,$2,exact'
    resizeSquare: 'resize:$1,$1'
    crop: 'crop:$1,$2,$3,$4'
    resizeCrop: 'resize:$1,$2,exact|crop:$3,$4,$5,$6'

Použití:

{img $image, resize(20,30,shrink)}
{img $image, resizeExact(20,30)}
{img $image, resizeSquare(10), crop(5,5,5,5)}

před 11 měsíci

cafesk8
Člen | 68
+
0
-

Zdravím,

máte někdo zkušenost s napojením na https://github.com/…y-FileUpload ? Ať dělám, co dělám, nedaří se mi to.

namespace App\Model;

use Nette\SmartObject;
use Nette\Utils\FileSystem;
use Zet\FileUpload\Model;
use WebChemistry\Images\IStorage;


class UploadFilesRepository implements \Zet\FileUpload\Model\IUploadModel {
    use SmartObject;


    /** @inject @var WebChemistry\Images\IStorage */
    public $storage;
    /** @inject @var Nette\Utils\Upload */
    public $upload;


    /**
     * Zpracování požadavku o smazání souboru.
     * @param $uploaded Hodnota navrácená funkcí save.
     */
    public function remove($uploaded) {
    }

    /**
     * Zpracování přejmenování souboru.
     * @param $upload Hodnota navrácená funkcí save.
     * @param $newName Nové jméno souboru.
     * @return mixed Vlastní návratová hodnota.
     */
    public function rename($upload, $newName) {
        Nette\Utils\FileSystem::rename($upload,"../www/advert_pics/".$newName);
    }

    /**
     * Uložení nahraného souboru.
     * @param \Nette\Http\FileUpload $file
     * @param array $params Pole vlastních hodnot.
     * @return mixed Vlastní navrátová hodnota.
     */
    public function save(\Nette\Http\FileUpload $file, array $params = []) {
        // vytvorime zdroj pro obrazek
        $resource = $this->storage->createUploadResource($upload);
        // pridame namespace
        $resource->setNamespace('namespace');
        // ulozime
        $result = $this->storage->save($resource);
        // zobrazime url adresu
        echo $this->storage->link($result);
    }

Vyhazuje mi to: Call to a member function createUploadResource() on null

Je mi jasné tedy, že $this->storage je null, nevím si rady jak si předat ten soubor.

Díky

před 11 měsíci

Mysteria
Člen | 719
+
0
-

Inject anotace fungují jenom v presenterech, předej si ty závislosti normálně přes konstruktor.

před 11 měsíci

cafesk8
Člen | 68
+
0
-

Mysteria napsal(a):

Inject anotace fungují jenom v presenterech, předej si ty závislosti normálně přes konstruktor.

Díky. Bohužel ani to se mi nedaří, asi to dělám úplně špatně.

namespace App\Model;

use Nette\SmartObject;
use Nette\Utils\FileSystem;
use Zet\FileUpload\Model;
use WebChemistry\Images\IStorage;


class UploadFilesRepository implements \Zet\FileUpload\Model\IUploadModel {
    use SmartObject;


    public $storage;
    public $upload;


    public function __construct () {
        $this->storage = new \WebChemistry\Images\IStorage;
        $this->upload = new \Nette\Utils\Upload ;
    }

    # další metody třídy
}

vyhazuje mi to

Class 'WebChemistry\Images\IStorage' not found

před 11 měsíci

Martk
Člen | 487
+
0
-
namespace App\Model;

use Nette\SmartObject;
use Nette\Utils\FileSystem;
use Zet\FileUpload\Model;
use WebChemistry\Images\IStorage;


class UploadFilesRepository implements \Zet\FileUpload\Model\IUploadModel {
    use SmartObject;


    public $storage;
    public $upload;


    public function __construct (IStorage $storage, Upload $upload) {
        $this->storage = $storage;
        $this->upload = $upload;
    }

    # další metody třídy
}

config.neon

services:
    - App\Model\UploadFilesRepository

presenter:

class CustomPresenter {

    /** App\Model\UploadFilesRepository @inject */
    public $repository;

}

cokoliv jiného, musíš to zaregistrovat jako UploadFilesRepository do configu:

class CustomService {

    public function __construct(App\Model\UploadFilesRepository $repository) { ... }

}

před 11 měsíci

cafesk8
Člen | 68
+
0
-

Martk napsal(a):

namespace App\Model;

use Nette\SmartObject;
use Nette\Utils\FileSystem;
use Zet\FileUpload\Model;
use WebChemistry\Images\IStorage;


class UploadFilesRepository implements \Zet\FileUpload\Model\IUploadModel {
    use SmartObject;


    public $storage;
    public $upload;


    public function __construct (IStorage $storage, Upload $upload) {
        $this->storage = $storage;
        $this->upload = $upload;
    }

    # další metody třídy
}

config.neon

services:
  - App\Model\UploadFilesRepository

presenter:

class CustomPresenter {

  /** App\Model\UploadFilesRepository @inject */
  public $repository;

}

cokoliv jiného, musíš to zaregistrovat jako UploadFilesRepository do configu:

class CustomService {

  public function __construct(App\Model\UploadFilesRepository $repository) { ... }

}
namespace App\Model;

use Nette\SmartObject;
use Nette\Utils\FileSystem;
use Zet\FileUpload\Model;
use WebChemistry\Images\IStorage;


class UploadFilesRepository implements \Zet\FileUpload\Model\IUploadModel {
    use SmartObject;

    public $storage;
    public $upload;


    public function __construct (WebChemistry\Images\IStorage $storage, Upload $upload) {
        $this->storage = $storage;
        $this->upload = $upload;
    }

Mi teď pro změnu vyhazuje

Service '36_App_Model_UploadFilesRepository' (type of App\Model\UploadFilesRepository): Class App\Model\WebChemistry\Images\IStorage needed by App\Model\UploadFilesRepository::__construct() not found. Check type hint and 'use' statements.

Není někde nějaký sandbox kterým bych se mohl inspirovat?

Díky

před 11 měsíci

Ondřej Kubíček
Člen | 393
+
0
-

tak ta hláška mluví jasně, máš špatně definovaný namespace
tohle:

... __construct (WebChemistry\Images\IStorage ...

hledá ve tvém namespacu App\Model\WebChemistry\Images\IStorage protože nemáš v use use WebChemistry

nebo opačně, mít v constructoru jen IStorage a v use WebChemistry\Images\IStorage

ale to jsou základy PHP, nemá s nette ani s addonem nic společného, a hlavně už i idečko ti muselo řvát, že to nenašlo tu třídu

Editoval Ondřej Kubíček (21. 6. 2018 15:13)

před 11 měsíci

cafesk8
Člen | 68
+
0
-

Problém byl v tom, že nic jako WebChemistry\Images\IStorage které se uvádí v dokumentaci neexistuje, jmenuje se to WebChemistry\Images\IImageStorage.

Editoval cafesk8 (26. 6. 2018 14:15)

před 11 měsíci

cafesk8
Člen | 68
+
0
-

Zdravím,

mám problém s vykreslením obrázků. Přes ID obrázku si načtu adresu obrázku a do šablony si tuto cestu předám.

$resource               = $this->imageStorage->createResource('moje_slozka/soubor.jpg');
$this->template->image  = $this->imageStorage->link($resource);

v šabloně při zavolání klasického {$image} se mi vypíše ‚/assets/moje_slozka/original/soubor.jpg‘ Což je v pořádku.

Problém nastane, když bych si chtěl obrázek vygenerovat a vypsat ve více velikostech, zkusil jsem si dát do config.neon:

aliases:
    resize: 'resize:$1,$2,$3'
    resizeExact: 'resize:$1,$2,exact'
    resizeSquare: 'resize:$1,$1'
    crop: 'crop:$1,$2,$3,$4'
    resizeCrop: 'resize:$1,$2,exact|crop:$3,$4,$5,$6'

Teď když zkusím v šabloně dát:

{img $image, resize(20,30,shrink)}
{img $image, resizeExact(20,30)}
{img $image, resizeSquare(10), crop(5,5,5,5)}

Tak mi vyskočí Undefined variable: _imageFacade viz. tato odpověď a dotaz nad ním . Dobře, tak jsem si do presenteru zaregistroval novou proměnnou a zároveň si ji předal do šablony

Super, hláška zmizela, ale teď {img $image} nezobrazí vůbec nic a {img $image resize(20,30,shrink}, apod. vyhazuje, že nejsou definované funkce jako je resize, resizeExact apod. Ty resizery apod se musí někde speciálně ještě napsat?

před 11 měsíci

Martk
Člen | 487
+
0
-
$this->template->image = $this->imageStorage->createResource(...);

nebo rovnou

{img 'moje_slozka/soubor.jpg', resize(20,30,shrink)}

Dokumentaci opravím, díky.

Editoval Martk (27. 6. 2018 10:17)

Stránky: Prev 1 2 3 4 RSS tématu