Comment puis-je obtenir la taille du fichier en temps réel d'un téléchargement lié au serveur ?

Susan Sarandon
Libérer: 2024-10-20 22:02:02
original
207 Les gens l'ont consulté

How Can I Get the Real-Time File Size of a Server-Bound Upload?

Question :

Obtenir la taille en temps réel d'un fichier téléchargé pendant son écriture sur le serveur sans bloquer à la fois le serveur et client.

Contexte :

Progression du téléchargement du fichier dans le navigateur d'un client lors de l'écriture sur le serveur à l'aide de la requête POST de fetch() avec un corps de fichier ou de blob.

Exigence :

Afficher la taille du fichier sous forme de texte/flux d'événements pendant son écriture sur le système de fichiers du serveur. Arrêtez-vous lorsque tous les octets fournis en tant que paramètre de chaîne de requête lors du téléchargement du fichier ont été écrits. La taille du fichier est actuellement récupérée à partir d'un script distinct, qui est appelé après que le fichier a été écrit sur le serveur.

Implémentation :

Initialement tenté d'utiliser PHP mais rencontré erreurs dues à un HTTP_LAST_EVENT_ID non défini et à une taille de fichier incorrecte signalée. J'ai également expérimenté différentes approches et langages comme bash, c, nodejs et python.

Solution :

  1. Effacer le cache des statistiques de fichiers pour obtenir un fichier en temps réel size :
<code class="php">clearstatcache(true, $upload);
$data = filesize($upload);</code>
Copier après la connexion
  1. stream.php modifié avec gestion des erreurs et utilisation de usleep pour de meilleures performances :
<code class="php">// Check if the header's been sent to avoid `PHP Notice:  Undefined index: HTTP_LAST_EVENT_ID in stream.php on line `
// php 7+
//$lastId = $_SERVER["HTTP_LAST_EVENT_ID"] ?? 0;
// php < 7
$lastId = isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? intval($_SERVER["HTTP_LAST_EVENT_ID"]) : 0;

$upload = $_GET["filename"];
$data = 0;
// if file already exists, its initial size can be bigger than the new one, so we need to ignore it
$wasLess = $lastId != 0;
while ($data < $_GET["filesize"] || !$wasLess) {
    // system calls are expensive and are being cached with assumption that in most cases file stats do not change often
    // so we clear cache to get most up to date data
    clearstatcache(true, $upload);
    $data = filesize($upload);
    $wasLess |= $data < $_GET["filesize"];
    // don't send stale filesize
    if ($wasLess) {
        sendMessage($lastId, $data);
        $lastId++;
    }
    // not necessary here, though without thousands of `message` events will be dispatched
    //sleep(1);
    // millions on poor connection and large files. 1 second might be too much, but 50 messages a second must be okay
    usleep(20000);
}</code>
Copier après la connexion
  1. Inclure fileId et fileSize dans le cadre de la requête POST et ajoutez un stockage en mémoire à l'aide de Redis ou Memcache pour stocker les métadonnées des fichiers.
  2. Utilisez EventSource dans le JavaScript côté client :
<code class="javascript">const [fileId, request, source] = [
    Math.random().toString(36).substr(2),
    new Request(`${url}?fileId=${fileId}&amp;size=${filesize}`, {
        method: "POST",
        headers: headers,
        body: file
    }),
    new EventSource(`${stream}?fileId=${fileId}`)
];</code>
Copier après la connexion
  1. Personnalisez les fonctions setUnique et updateProgress en fonction du mécanisme de stockage choisi :
<code class="php">function setUnique(string $id, int $size) {
    // implement with your storage of choice
}

function updateProgress(string $id, int $processed) {
    // implement with your storage of choice
}</code>
Copier après la connexion
  1. Obtenez la progression du stockage :
<code class="php">list($progress, $size) = getProgress($_GET["fileId"]);</code>
Copier après la connexion

Remarques importantes :

  • La solution fournie donne la priorité à la fonctionnalité plutôt qu'à la sécurité et n'est pas recommandée pour une utilisation en production sans mettre en œuvre des mesures de sécurité supplémentaires.
  • Le nombre de connexions ouvertes peut devoir être ajusté en fonction de la configuration du serveur et de l'utilisation des ressources.
  • Au lieu d'EventSource, l'utilisation de l'interrogation peut être envisagée pour réduire le nombre de connexions ouvertes, mais cela peut avoir un impact sur la réactivité.
  • Le temps de sommeil optimal en veille () peut varier en fonction de la fréquence de mise à jour souhaitée et des compromis en termes de performances.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!