การกระจายไฟล์จาก Google Drive โดยใช้ nginx

ประวัติศาสตร์

มันบังเอิญจนฉันต้องจัดเก็บข้อมูลมากกว่า 1.5 TB ไว้ที่ใดที่หนึ่ง และยังให้ความสามารถสำหรับผู้ใช้ทั่วไปในการดาวน์โหลดผ่านลิงก์โดยตรงอีกด้วย เนื่องจากตามเนื้อผ้าจำนวนหน่วยความจำดังกล่าวไปที่ VDS ค่าเช่าซึ่งไม่รวมอยู่ในงบประมาณโครงการมากนักจากหมวดหมู่ "ไม่มีอะไรให้ทำ" และจากข้อมูลต้นฉบับฉันมี VPS 400GB SSD ซึ่งแม้ว่าฉันจะ ต้องการฉันไม่สามารถใส่รูปภาพขนาด 1.5TB โดยไม่มีการบีบอัดแบบไม่สูญเสียข้อมูลได้ก็จะประสบความสำเร็จ

แล้วฉันก็จำได้ว่าถ้าฉันลบขยะออกจาก Google Drive เช่นโปรแกรมที่ทำงานบน Windows XP เท่านั้นและสิ่งอื่น ๆ ที่ย้ายจากอุปกรณ์เครื่องหนึ่งไปยังอีกเครื่องหนึ่งตั้งแต่สมัยที่อินเทอร์เน็ตไม่เร็วนักเลยไม่จำกัด ( ตัวอย่างเช่นกล่องเสมือนเวอร์ชัน 10-20 ไม่น่าจะมีค่าใด ๆ นอกเหนือจากความคิดถึง) ดังนั้นทุกอย่างควรจะเข้ากันได้ดีมาก พูดไม่ทันทำเลย ดังนั้น เมื่อทะลุขีดจำกัดจำนวนคำขอไปยัง API (อย่างไรก็ตาม การสนับสนุนทางเทคนิคโดยไม่มีปัญหาใด ๆ เพิ่มโควต้าคำขอต่อผู้ใช้เป็น 100 ใน 10 วินาที) ข้อมูลจึงไหลอย่างรวดเร็วไปยังสถานที่ที่มีการปรับใช้เพิ่มเติม .

ดูเหมือนทุกอย่างจะดี แต่ตอนนี้ต้องถ่ายทอดไปยังผู้ใช้ปลายทางแล้ว ยิ่งกว่านั้นโดยไม่มีการเปลี่ยนเส้นทางไปยังแหล่งข้อมูลอื่น แต่เพื่อให้บุคคลนั้นเพียงแค่กดปุ่ม "ดาวน์โหลด" และกลายเป็นเจ้าของไฟล์ที่มีค่าอย่างมีความสุข

โดยพระเจ้า ฉันประสบปัญหาทุกประเภท ตอนแรกมันเป็นสคริปต์ใน AmPHP แต่ฉันไม่พอใจกับโหลดที่สร้างขึ้น (เพิ่มขึ้นอย่างรวดเร็วตั้งแต่เริ่มต้นจนถึงการใช้คอร์ 100%) จากนั้นเครื่องห่อม้วนผมสำหรับ ReactPHP ก็เข้ามามีบทบาทซึ่งค่อนข้างตรงกับความต้องการของฉันในแง่ของจำนวนรอบของ CPU ที่ใช้ไป แต่ไม่ได้ให้ความเร็วตามที่ฉันต้องการเลย (ปรากฎว่าคุณสามารถลดช่วงเวลาการโทรได้อย่างง่ายดาย curl_multi_select แต่แล้วเราก็มีความตะกละคล้ายกับตัวเลือกแรก ) ฉันพยายามเขียนบริการเล็ก ๆ ใน Rust และมันก็ทำงานได้ค่อนข้างเร็ว (น่าประหลาดใจที่มันใช้งานได้เมื่อได้รับความรู้ของฉัน) แต่ฉันต้องการมากกว่านี้และมันก็ยากที่จะปรับแต่งมัน นอกจากนี้ โซลูชันทั้งหมดเหล่านี้ยังบัฟเฟอร์การตอบสนองอย่างแปลกประหลาด และฉันต้องการติดตามช่วงเวลาที่การดาวน์โหลดไฟล์สิ้นสุดลงด้วยความแม่นยำสูงสุด

โดยทั่วไปมันคดมาระยะหนึ่งแล้ว แต่มันก็ได้ผล จนกระทั่งวันหนึ่งฉันก็เกิดความคิดที่น่าทึ่งในความบ้าคลั่งของมัน: ตามทฤษฎีแล้ว nginx สามารถทำสิ่งที่ฉันต้องการ ทำงานได้อย่างรวดเร็ว และแม้แต่ยอมให้เกิดความวิปริตทุกประเภทด้วยการกำหนดค่า เราต้องลอง - แล้วถ้ามันได้ผลล่ะ? และหลังจากครึ่งวันของการค้นหาอย่างต่อเนื่อง วิธีแก้ปัญหาก็เกิดขึ้นซึ่งทำงานได้เสถียรมาหลายเดือนและตรงตามความต้องการทั้งหมดของฉัน

การตั้งค่า 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;
}

ฉบับย่อที่ไม่มีความคิดเห็นสามารถดูได้ใต้สปอยเลอร์

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;
}

เรากำลังเขียนบทเพื่อจัดการความสุขทั้งหมดนี้

ตัวอย่างจะเป็น PHP และจงใจเขียนโดยใช้ชุดอุปกรณ์ขั้นต่ำ ฉันคิดว่าใครก็ตามที่มีประสบการณ์กับภาษาอื่นจะสามารถรวมส่วนนี้โดยใช้ตัวอย่างของฉันได้

<?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));

ผลของการ

โดยทั่วไป วิธีนี้ช่วยให้จัดระเบียบการกระจายไฟล์ไปยังผู้ใช้จากที่เก็บข้อมูลบนคลาวด์ได้อย่างง่ายดาย ใช่ แม้จะมาจากโทรเลขหรือ VK ก็ตาม (โดยที่ขนาดไฟล์ต้องไม่เกินขนาดที่อนุญาตของที่เก็บข้อมูลนี้) ฉันมีความคิดที่คล้ายกัน นี้แต่น่าเสียดายที่ฉันเจอไฟล์ที่มีขนาดสูงสุด 2GB และฉันยังไม่พบวิธีการหรือโมดูลสำหรับการติดการตอบสนองจากอัปสตรีม และการเขียน wrapper บางประเภทสำหรับโปรเจ็กต์นี้ต้องใช้แรงงานมากเกินสมควร

ขอขอบคุณสำหรับความสนใจของคุณ. ฉันหวังว่าเรื่องราวของฉันจะน่าสนใจหรือเป็นประโยชน์กับคุณเป็นอย่างน้อย

ที่มา: will.com

เพิ่มความคิดเห็น