Nous distribuons des fichiers à partir de Google Drive en utilisant nginx

Contexte


Il s'est avéré que j'avais besoin d'un endroit pour stocker plus de 1,5 To de données, et même fournir la possibilité de les télécharger par des utilisateurs ordinaires via un lien direct. Étant donné que traditionnellement, de telles quantités de mémoire vont déjà au VDS, dont le coût de location n'est pas trop investi dans le budget du projet de la catégorie «rien à faire», et des données sources, j'avais un SSD VPS 400 Go, où je ne pouvais pas mettre 1,5 To d'images sans compression sans perte va réussir.


Et puis je me suis souvenu que si vous supprimez les fichiers indésirables du disque Google, comme les programmes qui s'exécutent uniquement sur Windows XP, et d'autres choses qui se déplacent de mes médias vers les médias car Internet n'était pas si rapide et complètement pas illimité (par exemple, ces versions 10-20 de la boîte virtuelle étaient peu susceptibles d'avoir une valeur autre que nostalgique), alors tout devrait très bien s'adapter. Aussitôt dit, aussitôt fait. Et donc, franchissant la limite du nombre de demandes vers l'API (en passant, le support technique sans problème a augmenté le quota de demandes par utilisateur en 100 secondes à 10000), les données ont rapidement circulé vers le lieu de leur déploiement ultérieur.


Tout semble aller bien, mais maintenant il faut le transmettre à l'utilisateur final. De plus, sans aucune redirection vers d'autres ressources là-bas, et de sorte qu'une personne clique simplement sur le bouton "Télécharger" et devienne l'heureux propriétaire du fichier précieux.


Puis, par golly, je suis parti de toutes les manières sérieuses. Au début, c'était un script sur AmPHP, mais je n'étais pas satisfait de la charge qu'il avait créée (un bond en avant au démarrage à 100% de la consommation du noyau). Ensuite, l'encapsuleur de boucles pour ReactPHP est entré en action, ce qui correspond parfaitement à mes souhaits pour le nombre de cycles d'horloge du processeur consommé, mais il n'a pas donné la vitesse du tout ce que je voulais (il s'est avéré que vous pouvez simplement réduire l'intervalle d'appel curl_multi_select, mais nous avons alors la même gourmandise pour la première option ) J'ai même essayé d'écrire un petit service en Rust, et cela a fonctionné assez rapidement (même de manière surprenante, cela a fonctionné à ma connaissance), mais j'en voulais plus, et ce n'était pas facile de le personnaliser. En outre, toutes ces solutions ont étrangement tamponné la réponse, et je voulais suivre le moment où le téléchargement du fichier avec la plus grande précision s'est terminé.


En général, pendant un moment, c'était de travers, mais cela a fonctionné. Jusqu'au jour où j'ai eu l'idée d'une merveilleuse idée délirante: en théorie, nginx peut faire ce que je veux, il fonctionne rapidement et permet même toutes sortes de perversions avec la configuration. Vous devez essayer - et si cela fonctionne? Et après une demi-journée de recherches persistantes, une solution fonctionnait de manière stable depuis plusieurs mois et répondait à toutes mes exigences.


Personnalisez NGINX


#         . location ~* ^/google_drive/(.+)$ { #       (,     ). internal; #       (  ). limit_rate 1m; #   nginx    google drive    . resolver 8.8.8.8; # C     (    ). set $download_url https://www.googleapis.com/drive/v3/files/$upstream_http_file_id?alt=media; #    Content-Disposition ,        . set $content_disposition 'attachment; filename="$upstream_http_filename"'; #     . proxy_max_temp_file_size 0; # ,  ,     (  ,     $http_upstream    .   ,     -  ,      ). proxy_set_header Authorization 'Bearer $1'; #  ,         . proxy_pass $download_url; #              . add_header Content-Disposition $content_disposition; #        . proxy_hide_header Content-Disposition; proxy_hide_header Alt-Svc; proxy_hide_header Expires; proxy_hide_header Cache-Control; proxy_hide_header Vary; proxy_hide_header X-Goog-Hash; proxy_hide_header X-GUploader-UploadID; } 

Une version courte sans commentaires peut être vue sous le spoiler
 location ~* ^/google_drive/(.+)$ { internal; limit_rate 1m; resolver 8.8.8.8; set $download_url https://www.googleapis.com/drive/v3/files/$upstream_http_file_id?alt=media; set $content_disposition 'attachment; filename="$upstream_http_filename"'; proxy_max_temp_file_size 0; proxy_set_header Authorization 'Bearer $1'; proxy_pass $download_url; add_header Content-Disposition $content_disposition; proxy_hide_header Content-Disposition; proxy_hide_header Alt-Svc; proxy_hide_header Expires; proxy_hide_header Cache-Control; proxy_hide_header Vary; proxy_hide_header X-Goog-Hash; proxy_hide_header X-GUploader-UploadID; } 



Écrire un script pour gérer tout ce bonheur


L'exemple sera en PHP et volontairement écrit avec un kit de carrosserie minimum. Je pense que tous ceux qui ont de l'expérience avec une autre langue pourront intégrer cet article en utilisant mon exemple.


 <?php #   Google Drive Api. define('TOKEN', '*****'); # ID     $fileId = 'abcdefghijklmnopqrstuvwxyz1234567890'; # ,         -    ? http_response_code(204); #   c ID  (  nginx      $upstream_http_file_id). header('File-Id: ' . $fileId); #      ( $upstream_http_filename). header('Filename: ' . 'test.zip'); #  .       ,  ,     $1  nginx. header('X-Accel-Redirect: ' . rawurlencode('/google_drive/' . TOKEN)); 

Résumé


En général, cette méthode facilite l'organisation de la distribution des fichiers aux utilisateurs à partir de n'importe quel stockage cloud. Oui, même à partir d'un télégramme ou de VK (à condition que la taille du fichier ne dépasse pas la taille autorisée pour ce référentiel). J'avais une idée similaire à celle-ci , mais malheureusement je rencontre des fichiers jusqu'à 2 Go, et je n'ai pas encore trouvé de moyen ou de module pour coller les réponses en amont, écrire des wrappers pour ce projet est déraisonnablement laborieux.


Merci de votre attention. J'espère que mon histoire vous a été au moins un peu intéressante ou utile.

Source: https://habr.com/ru/post/fr460685/


All Articles