Skip to content

Nahrávání souborů - Dropzone

Systém pro nahrávání souborů s drag-and-drop interfacem přes Dropzone.js.

Podporuje chunked upload (rozdělení velkých souborů na menší části), automatické opakování při selhání a validaci typů souborů.

Příklad: Fotogalerie (#101)

Praktický příklad v admin panelu.

Konfigurace:

  • Formáty: WebP, JPEG, PNG
  • Max velikost: 50 MB
  • Chunking: 1 MB kousky s 3 pokusy o retry
  • Sekvenční upload: 1 soubor najednou

Implementace

1. Definice v YAML

form_fields_add_photos:
  -
    section: start
    title: Photos
  -
    name: file1
    label: Photos
    action: uploadPhoto
    id: 101
    text: "Přetáhněte sem soubory nebo klikněte pro nahrání."
    element:
      type: files

Důležité:

  • id - DOM element ID pro Dropzone
  • action - Metoda kontroleru
  • element.type - Určuje metodu v FormFieldFactory (např. uploadPhotocreateUploadPhoto(), filescreateFiles(), cFilescreateCFiles(), atd.)

2. JS inicializace

src/backend/js/dropzone/files.js - Sdílená konfigurace pro všechny varianty:

// Sdílené i18n messages
const sharedMessages = { ... };

// Sdílená nastavení chunking
const sharedChunkingConfig = {
    chunking: true,
    forceChunking: true,
    chunkSize: 1048576,    // 1 MB
    retryChunks: true,
    retryChunksLimit: 3,
    parallelUploads: 1,
};

// Inicializace pro konkrétní upload
const element = document.getElementById('dropzone101');
if (element) {
    new Dropzone('#dropzone101', {
        url: element.getAttribute('data-url'),
        acceptedFiles: 'image/webp,image/jpeg,image/png',
        ...sharedMessages,
        ...sharedChunkingConfig,
        // event handlers...
    });
}

Viz dokumentace Dropzone options

3. Backend handler

PhotogalleryController::uploadPhoto():

public function uploadPhoto(): void
{
    $response = DropzoneHandler::upload();

    // Nebo s vlastní konfigurací:
    // $response = DropzoneHandler::upload([
    //     'maxFileSizeMB' => 50,
    //     'allowedExtensions' => ['jpg', 'jpeg', 'png', 'webp'],
    // ]);

    if (!empty($response['error'])) {
        Debugger::log($response['error'], Debugger::ERROR);
        echo $response['error'];
    }

    if (!empty($response['status'])) {
        echo $response['status'];  // Chunk received...
    }

    if (!empty($response['name'])) {
        // Soubor hotov - zpracovat
        if ($this->savePhoto($response)) {
            $this->mainPhoto(false);
            $this->write_gallery($this->gallery, false);
            $this->change_count_photos();
        }
    }

    exit;
}

DropzoneHandler

Třída core/Upload/DropzoneHandler.php - statická metoda upload():

Bezpečnostní kontroly:

  • Blokuje PHP, HTML, JS soubory vždy
  • Validuje velikost souboru
  • Při nastavení allowedExtensions povolí jen ty

Chunking:

  • Dělí soubor na 1 MB kousky (konfigurovatelně)
  • Skládá kousky, zpět když přijde poslední

Vrací:

[
    'name' => 'soubor.jpg',
    'path' => '/var/tmp/soubor.jpg',
    'status' => 'Success. File uploaded.'
]
// nebo
['error' => 'Chybová zpráva']

Konfigurace:

$options = [
    'path' => DIR . '/var/tmp/',              // Kam ukládat dočasně
    'maxFileSizeMB' => 50,                    // Max velikost MB
    'paramName' => 'dzFile',                  // POST param jméno
    'allowedExtensions' => ['jpg', 'png'],    // null = bez omezení (jen bezpečnostní)
];

Plánované varianty

Struktura je připravena na přidání dalších upload typů (cUpload, uploadFile, atd.).

Každá varianta si bude číst konfiguraci z data-* atributů:

  • data-url - Upload endpoint
  • data-accept - MIME types
  • data-message - Custom zpráva

Poznámky

  • Soubory se nejdřív ukládají do /var/tmp/ (dočasně)
  • Kontroler si je převezme, případně zprocessuje a uloží finálně
  • Chunking obchází post_max_size limit PHP
  • Automatické retry na selhání komunikace