Fișierele temporare sunt gestionate de file_file_download()
, o implementare a hook_file_download()
realizat din modulul Fișier. Codul pe care îl folosește este următorul.
// Aflați dacă un fișier temporar este încă folosit în sistem.
dacă ($fișier->esteTemporary()) {
$usage = \Drupal::service('file.usage')->listUsage($file);
if (empty($usage) && $file->getOwnerId() != \Drupal::currentUser()
->id()) {
// Interzice accesul la fișierele temporare fără utilizare care nu sunt deținute de
// același utilizator. Acest lucru previne problema de securitate pe care un fișier privat care
// a fost protejat de permisiunile de câmp devine disponibil după utilizarea sa
// a fost eliminat și înainte de a fi șters efectiv din sistemul de fișiere.
// Modulele care depind de acest comportament ar trebui să facă fișierul permanent
// in schimb.
întoarcere -1;
}
}
Citirea comentariilor, care se face intenționat pentru a evita un fișier privat, protejat de permisiuni de câmp, este vizibilă după modificarea permisiunilor de câmp, dar înainte ca fișierul să fie șters.
Privind codul care invocă acel cârlig, în FileDownloadController::download()
de exemplu, nu văd nicio modalitate de a evita asta, deoarece codul nu folosește hook_file_download_alter()
.
O soluție ar putea fi setarea acel fișier ca fiind utilizat, deoarece codul verifică că fișierul nu este utilizat, înainte de a bloca accesul.
funcția mymodule_file_download($uri) {
if (StreamWrapperManager::getScheme($uri) == 'temporar') {
if ($fișiere = \Drupal::entityTypeManager()->getStorage('fișier')->loadByProperties(['uri' => $uri])){
if ($fișier = resetare($fișiere)) {
// Accesul este permis.
\Drupal::service('file.usage')->add($file, 'mymodule', 'unexisting_entity', 10);
$headers = file_get_content_headers($fișier);
returnează $headers;
}
}
}
}
obisnuiam „entitate_inexistentă”
și 10 ca tip de entitate și ID de entitate. Dacă aveți valori reale pentru ei, ar trebui să le folosiți.
Rețineți că FileUsageBase::add()
, cel DatabaseFileUsageBackend::add()
metoda părinte, schimbă fișierul în permanent, în cazul în care nu este deja.
// Asigurați-vă că un fișier folosit este permanent.
dacă (!$fișier->isPermanent()) {
$fișier->setPermanent();
$fișier->salvare();
}
Când utilizarea unui fișier este redusă și devine 0, fișierul este schimbat în temporar de la FileUsageBase::delete()
.
// Dacă nu mai există utilizări rămase ale acestui fișier, marcați-l ca temporar,
// care are ca rezultat o ștergere prin system_cron().
$usage = \Drupal::service('file.usage')->listUsage($file);
dacă (gol ($utilizare)) {
$fișier->setTemporary();
$fișier->salvare();
}
Aș prefera să măresc utilizarea fișierului, în loc să fac direct un fișier permanent, deoarece scăderea utilizării fișierului nu intră în conflict cu alte module care ar putea seta același fișier ca fiind permanent.
Alternativ, aș folosi următorul cod pentru hook_file_download()
.
funcția mymodule_file_download($uri) {
if (StreamWrapperManager::getScheme($uri) == 'temporar') {
if ($fișiere = \Drupal::entityTypeManager()->getStorage('fișier')->loadByProperties(['uri' => $uri])){
if ($fișier = resetare($fișiere)) {
// Accesul este permis.
dacă (!$fișier->isPermanent()) {
$fișier->setPermanent();
$fișier->salvare();
}
$headers = file_get_content_headers($fișier);
returnează $headers;
}
}
}
}
În acest caz, pentru a face din nou fișierul temporar, aș folosi următorul cod.
// Stochează referința entității fișierului în $file.
$usage = \Drupal::service('file.usage')->listUsage($file);
if (gol ($utilizare) && !$fișier->isTemporary()) {
$fișier->setTemporary();
$fișier->salvare();
}
Pentru a obține ceea ce doriți, ar fi, de asemenea, posibil să schimbați controlerul pentru sistem.temporar traseu, dar asta pare excesiv.