У меня очень неприятная проблема, а PDF-файлы, которые я пытаюсь загрузить с сайта, испорчены. Они генерируются нормально (я вижу, что если я загружу его через SFTP из временной папки, они будут помещены в него).
location ~ \.cgi$ {
#try_files $uri =404;
gzip off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8181;
}
Код Perl довольно прост (я не буду также вставлять код генерации PDF, так как он работает нормально);
my $filepath = qq|/home/fatpeter/web/site.com/cgi-bin/hotels/admin/tmp_pdf/| . CORE::time() . q|.pdf|;
$pdf->to_file($filepath);
$file_name =~ s/\-/_/sig;
my $size = -s $filepath;
my $file = \do { local *FH; *FH };
open $file, "<$filepath" or die "Unable to open file '$filepath': $!";
binmode $file;
binmode STDOUT;
print $IN->header($IN->file_headers(
filename => $file_name,
mimetype => 'application/pdf',
inline => 0,
size => $size
));
{
local $\;
while (read($file, my $chunk, 4096)) {
print $chunk;
}
}
Таким образом, в основном nginx передает запрос Apache2.4, затем запускается Perl и создает PDF-файл. Затем скрипт возвращает им PDF-файл.
[Вт, 25 апреля, 13:41: 36.810922 2017] [: ошибка] [pid 2901]: Apache2 IO write: (104) Сброс соединения одноранговым узлом на /home/fatpeter/web/site.com/cgi-bin/hotels/invoices .cgi строка 285
Строка 285 - это while () { }
цикл:
while (read($file, my $chunk, 4096)) {
Я не понимаю, почему он отключал его до загрузки. Любые идеи? Как бы то ни было, размер тестового файла, который я использую, составляет 363 КБ (372 596 байт), так что он не очень большой! Мои настройки прокси в основном nginx.conf файлы:
proxy_redirect выключен; proxy_set_header Host $ host; proxy_set_header X-Real-IP $ remote_addr; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffers 32 4k;
Это то, что скрипт отправляет в виде заголовков:
Content-type: application/pdf
Content-Disposition: attachment; filename="foo.pdf"; size=372596
Content-Length: 372596
ОБНОВИТЬ: Интересно, что теперь я получаю это сообщение об ошибке в Firefox при загрузке:
C: \ Users \ Andy \ AppData \ Local \ Temp \ Jy4tj5pr.pdf.part не может быть сохранен, так как исходный файл не может быть прочитан.
Повторите попытку позже или обратитесь к администратору сервера.
Я также теперь вижу это в журнале доступа:
127.0.0.1 - - [25/Apr/2017:15:29:38 +0000] "GET /cgi-bin/hotels/invoices.cgi?action=download;id=60d90acf677e9c81;invoice=1055;t=french HTTP/1.0" 200 372861 "https://www.example.com/cgi-bin/hotels/invoices.cgi?t=french" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"
81.174.134.133 - - [25/Apr/2017:15:29:38 +0000] "GET /cgi-bin/hotels/invoices.cgi?action=download;id=60d90acf677e9c81;invoice=1055;t=french HTTP/2.0" 200 372616 "https://www.example.com/cgi-bin/hotels/invoices.cgi?t=french" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"
ОБНОВЛЕНИЕ 3: Хорошо, поэтому я подхожу немного ближе. Проблема, похоже, связана с "фрагментированием" в сценарии:
while (read($file, my $chunk, 4096)) {
Если я изменю это, например, на:
while (read($file, my $chunk, 409600)) {
(больше, чем размер рассматриваемого файла), он РАБОТАЕТ! Но проблема в том, что мне делать с большими файлами?
Итак, вот рабочий код:
{
local $\;
while (read($file, my $chunk, -s $filepath)) {
print $chunk;
}
}
Мне просто не нравится мысль о невозможности отправлять его блоками. Есть ли недостатки в том, чтобы делать это таким образом?