Dosbarthu ffeiliau o Google Drive gan ddefnyddio nginx

cynhanes

Digwyddodd felly bod angen i mi storio mwy na 1.5 TB o ddata yn rhywle, a hefyd darparu'r gallu i ddefnyddwyr cyffredin ei lawrlwytho trwy ddolen uniongyrchol. Gan fod cymaint o gof yn draddodiadol yn mynd i VDS, mae cost rhentu nad yw wedi'i chynnwys yn fawr iawn yng nghyllideb y prosiect o'r categori “dim byd i'w wneud”, ac o'r data ffynhonnell roedd gen i SSD VPS 400GB, lle, hyd yn oed os ydw i eisiau, ni allwn roi 1.5TB o ddelweddau heb cywasgu lossless bydd yn llwyddo.

Ac yna cofiais, os byddaf yn dileu sothach o Google Drive, fel rhaglenni a fydd ond yn rhedeg ar Windows XP, a phethau eraill sydd wedi bod yn symud o un ddyfais i'r llall ers y dyddiau pan nad oedd y Rhyngrwyd mor gyflym o gwbl heb fod yn ddiderfyn ( er enghraifft, roedd y fersiynau 10-20 hynny o'r blwch rhithwir yn annhebygol o fod ag unrhyw werth heblaw hiraethu), yna dylai popeth gyd-fynd yn dda iawn. Nid cynt wedi dweud na gwneud. Ac felly, gan dorri trwy'r terfyn ar nifer y ceisiadau i'r ap (gyda llaw, cynyddodd cymorth technegol heb unrhyw broblemau y cwota o geisiadau fesul defnyddiwr i 100 mewn 10 eiliad), llifodd y data yn gyflym i'r man lle y'i defnyddiwyd ymhellach. .

Mae'n ymddangos bod popeth yn dda, ond nawr mae angen ei gyfleu i'r defnyddiwr terfynol. Ar ben hynny, heb unrhyw ailgyfeiriadau i adnoddau eraill, ond fel bod person yn syml yn pwyso'r botwm "Lawrlwytho" a dod yn berchennog hapus y ffeil drysor.

Yma, gan Dduw, es i bob math o drafferthion. Ar y dechrau roedd yn sgript yn AmPHP, ond nid oeddwn yn fodlon â'r llwyth a greodd (naid sydyn ar y dechrau i ddefnydd craidd 100%). Yna daeth y peiriant lapio cyrl ar gyfer ReactPHP i mewn, a oedd yn cyd-fynd yn eithaf â'm dymuniadau o ran nifer y cylchoedd CPU a ddefnyddiwyd, ond ni roddodd y cyflymder o gwbl yr hyn yr oeddwn ei eisiau (daeth allan y gallwch chi leihau'r egwyl galw curl_multi_select , ond yna mae gennym ni gluttony tebyg i'r opsiwn cyntaf ). Ceisiais hyd yn oed ysgrifennu gwasanaeth bach yn Rust, ac fe weithiodd yn eithaf cyflym (mae'n syndod ei fod yn gweithio, o ystyried fy ngwybodaeth), ond roeddwn i eisiau mwy, ac roedd yn anodd ei addasu rywsut. Yn ogystal, roedd yr holl atebion hyn rywsut yn clustogi'r ymateb yn rhyfedd, ac roeddwn i eisiau olrhain y foment pan ddaeth y lawrlwythiad ffeil i ben gyda'r cywirdeb mwyaf.

Yn gyffredinol, roedd yn gam am ychydig, ond fe weithiodd. Tan un diwrnod fe wnes i feddwl am syniad a oedd yn hynod yn ei wallgofrwydd: gall nginx, mewn theori, wneud yr hyn rydw i ei eisiau, gweithio'n gyflym, a hyd yn oed ganiatáu pob math o wyrdroadau gyda chyfluniad. Mae'n rhaid i ni geisio - beth os yw'n gweithio? Ac ar ôl hanner diwrnod o chwilio parhaus, datblygwyd datrysiad a oedd wedi bod yn gweithio'n sefydlog ers sawl mis ac a oedd yn bodloni fy holl ofynion.

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

Mae fersiwn byr heb sylwadau i'w weld o dan y sbwyliwr

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

Rydym yn ysgrifennu sgript i reoli'r holl hapusrwydd hwn

Bydd yr enghraifft yn PHP ac wedi'i hysgrifennu'n fwriadol gydag isafswm o offer. Rwy'n meddwl y bydd unrhyw un sydd â phrofiad gydag unrhyw iaith arall yn gallu integreiddio'r adran hon gan ddefnyddio fy enghraifft.

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

Canlyniadau

Yn gyffredinol, mae'r dull hwn yn ei gwneud hi'n eithaf hawdd trefnu dosbarthiad ffeiliau i ddefnyddwyr o unrhyw storfa cwmwl. Oes, hyd yn oed o telegram neu VK, (ar yr amod nad yw maint y ffeil yn fwy na maint a ganiateir y storfa hon). Roedd gen i syniad tebyg i hwn, ond yn anffodus rwy'n dod ar draws ffeiliau hyd at 2GB, ac nid wyf eto wedi dod o hyd i ddull neu fodiwl ar gyfer gludo ymatebion o i fyny'r afon, ac mae ysgrifennu rhyw fath o ddeunydd lapio ar gyfer y prosiect hwn yn afresymol o lafur-ddwys.

Diolch am eich sylw. Rwy'n gobeithio bod fy stori o leiaf ychydig yn ddiddorol neu'n ddefnyddiol i chi.

Ffynhonnell: hab.com

Ychwanegu sylw