Créer et diffuser une grande archive sans le stocker dans la mémoire ou sur le disque
Je veux permettre aux utilisateurs de télécharger une archive de plusieurs gros fichiers à la fois. Toutefois, les fichiers et les archives peuvent être trop grande pour stocker dans la mémoire ou sur le disque sur mon serveur (ils sont diffusés à partir d'autres serveurs à la volée). J'aimerais générer l'archive que j'ai de le transmettre à l'utilisateur.
Je peux utiliser Tar ou Zip ou tout ce qui est plus simple. Je suis à l'aide de django, ce qui me permet de retourner un générateur ou d'un fichier-comme l'objet de ma réponse. Cet objet pourrait être utilisée pour pomper le processus. Cependant, j'ai du mal à comprendre comment construire ce genre de chose autour de la zipfile ou tarfile bibliothèques, et je crains qu'ils ne peuvent pas prendre en charge la lecture des fichiers comme ils vont, ou la lecture de l'archive comme il est construit.
Cette réponse sur la conversion d'un itérateur vers un fichier objet en forme de pourrait aider. tarfile#addfile
prend un objet iterable, mais il semble passer immédiatement que pour shutil.copyfileobj
, si cela peut ne pas être en tant que générateur d'-friendly comme je l'avais espéré.
- En général, les utilitaires de compression zip ou tar besoin pour lire l'intégralité du fichier d'entrée afin de déterminer ce qui peut et doit être compressé. Donc je pense que votre architecture idée est erronée.
- tout à fait erronée;
tar
est juste un conteneur, pas de compression. Il a été conçu pour travailler avec les bandes-où la lecture de l'ensemble de la chose, il était hors de question. Etzlib
sera heureux de compresser un flux de données. Vous pouvez obtenir une meilleure compression avec plein de connaissance des fichiers, mais ce n'est pas obligatoire. - Je suppose qu'il voulait dire une archive compressée depuis qu'il parlait de la compression. Et zlib doit encore cache un certain nombre d'octets d'entrée avant de générer une sortie parce que la même exigence d'analyser les données d'entrée reste. Je suis d'accord, je me suis mal exprimée avec "ensemble", mais je maintiens que cela n'a guère de sens tant que la quantité de données vous permettra d'économiser par la compression de petits tronçons de cours d'eau sera négligeable à la quantité de travail consacré à la rédaction.
- la réponse plus nuancée est nettement meilleure, mais se demander si les données proviennent de l'antenne radio ou d'un microphone -- il pourrait y avoir amplement l'occasion de magasin de flux de données dans un format plus pratique pour le transfert et le déballage sans stockage de toutes les données pour l'analyse.
- Je n'ai jamais mentionné de compression. La Compression peut être géré par apache mod_gzip. Aussi, je ne sais pas ce que vous entendez à propos de "sauvegarde de données". Le but ici est de réduire l'utilisation de la mémoire sur le serveur, lui permettant tout simplement de flux de données d'un endroit à l'autre sans jamais se tenant sur trop de données à la fois.
- Le format tar ne semble pas si mauvaise; vous pouvez avoir besoin d'écrire vos propres outils, si la norme API ne pas fournir ce dont vous avez besoin.
- Je n'ai pas dit que l'enregistrement des données donc je ne sais pas à quoi vous faites référence. Mais si, en dépit de parler zip et les archives, vous ne voulez pas gérer la compression, tous mes points sont hypothétiques.
- Êtes-vous en mesure d'obtenir le fichier taille des fichiers que vous êtes en streaming sans téléchargement de l'intégralité du fichier? Si donc vous devriez être en mesure de paquet les fichiers dans un tar selon spécifications
Vous devez vous connecter pour publier un commentaire.
J'ai fini par utiliser SpiderOak ZipStream.
Vous pouvez le faire par la production et la diffusion d'un fichier zip avec aucune compression, ce qui est fondamentalement juste ajouter les en-têtes avant chaque contenu du fichier. Vous avez raison, les bibliothèques ne prennent pas en charge, mais vous pouvez pirater autour d'eux pour les faire fonctionner.
Ce code est renvoyé zipfile.ZipFile avec une classe qui gère les flux et de créer des instances de zipfile.ZipInfo pour les fichiers comme ils viennent. La CRC et de la taille peut être réglée à la fin. Vous pouvez envoyer des données à partir du flux d'entrée avec put_file(), write() et flush(), et de lire les données pour les flux de sortie avec read().
Gardez à l'esprit que ce code était juste une petite preuve de concept et je n'ai pas de développement ou de test une fois que j'ai décidé de laisser le serveur http lui-même faire face à ce problème. Quelques choses que vous devriez regarder dans si vous décidez de l'utiliser est de vérifier si les dossiers imbriqués sont archivés correctement, et le nom de l'encodage (qui est toujours une douleur, avec des fichiers zip de toute façon).
Vous pouvez diffuser un ZipFile à un Pylônes ou Django réponse fileobj par emballage de la fileobj dans quelque chose de fichiers qui implémente
tell()
. Ce sera tampon de chaque fichier dans le zip dans la mémoire, mais le flux de la zip de lui-même. Nous l'utiliser pour diffuser de télécharger un fichier zip pleine d'images, de sorte que nous n'avons jamais tampon plus qu'une seule image dans la mémoire.Cet exemple, les flux de
sys.stdout
. Pour les poteaux utilisationresponse.body_file
, pour Django, vous pouvez utiliser leHttpResponse
lui-même comme un fichier.this is hello{0} contents\n
est de 10 go taille?Voici la solution de Pedro Werneck (à partir de ci-dessus), mais avec un correctif pour éviter la collecte de toutes les données dans la mémoire (
read
méthode est fixe un peu):ensuite, vous pouvez utiliser
stream_generator
fonctionner comme un flux de données pour un fichier zipexemple pour Falcon:
pour python 3, vous pouvez utiliser Zip-Streaming
https://github.com/BuzonIO/zip_streaming
et