У меня очень странная проблема с загрузкой файлов размером более 6 ГБ. Мой процесс работает следующим образом:
Моя конфигурация PHP (HHVM) и NGINX имеет свою конфигурацию, позволяющую до 16 ГБ файла, мой тестовый файл – всего 8 ГБ.
Вот странная часть, ajax ВСЕГДА будет время. Но файл успешно загружен, его копируют в местоположение tmp, место, хранящееся в db, s3 и т. Д. Но AJAX работает в течение часа даже ПОСЛЕ завершения выполнения (что занимает 10-15 минут) и только заканчивается при выходе из строя.
Что может заставить сервер не отправлять ответ только для больших файлов?
Также журналы ошибок на стороне сервера пустые.
Большая загрузка файла является дорогостоящей и подверженной ошибкам операции. Nginx и backend должны иметь правильные границы тайм-аута для обработки медленного ввода-вывода IO, если таковые имеются. Теоретически просто управлять загрузкой файлов с использованием кодирования multipart / form-data RFC 1867.
Согласно developer.mozilla.org в купе multipart / form-data, общий заголовок HTTP Content-Disposition – это заголовок, который можно использовать в подразделе многочастного тела, чтобы предоставить информацию о поле, к которому оно относится. Подчасти разделяется границей, определенной в заголовке Content-Type. Используемый на самом теле, Content-Disposition не влияет.
Посмотрим, что происходит во время загрузки файла:
1) клиент отправляет HTTP-запрос с содержимым файла на веб-сервер
2) веб-сервер принимает запрос и инициирует передачу данных (или возвращает ошибку 413, если размер файла превышает лимит)
3) webserver начинает заполнять буферы (зависит от размера файлов и буферов)
4) веб-сервер отправляет содержимое файла через файловый / сетевой сокет на бэкэнд
5) бэкэнд аутентифицирует первоначальный запрос
6) бэкэнд читает файл и разрезает заголовки (Content-Disposition, Content-Type)
7) Бэкэнд-дамп привел файл на диск
8) любые последующие процедуры, такие как изменения базы данных
Во время загрузки больших файлов возникает несколько проблем:
Начнем с того, что Nginx настроен на новое местоположение http: // backend / upload для получения большой загрузки файла, минимизируется взаимодействие с исходным кодом (Content-Legth: 0), файл хранится только на диске. Использование буферов Nginx выгружает файл на диск (файл, хранящийся во временном каталоге со случайным именем, его нельзя изменить), а затем запрос POST для backend к адресу http: // backend / file с именем файла в X-File- Заголовок заголовка.
Чтобы сохранить дополнительную информацию, вы можете использовать заголовки с первоначальным запросом POST. Например, если заголовки заголовков X-Original-File-Name из первоначальных запросов помогают вам сопоставлять файл и хранить необходимую информацию о карте в базе данных.
Посмотрим, как это произойдет:
1) настройте Nginx для выгрузки содержимого тела HTTP в файл и храните его в файле client_body_in_file_only;
2) создать новую конечную точку http: // backend / file для обработки сопоставления между именем файла temp и заголовком X-File-Name
4) запрос AJAX инструмента с заголовком X-File-Name Nginx будет использовать для отправки запроса на отправку сообщений с
Конфигурация:
location /upload { client_body_temp_path /tmp/; client_body_in_file_only on; client_body_buffer_size 1M; client_max_body_size 7G; proxy_pass_request_headers on; proxy_set_header X-File-Name $request_body_file; proxy_set_body off; proxy_redirect off; proxy_pass http://backend/file; }
Опция конфигурации Nginx client_body_in_file_only несовместима с многофайловой загрузкой данных, но вы можете использовать ее с AJAX, т.е. XMLHttpRequest2 (двоичные данные).
Если вам нужна внутренняя аутентификация, можно использовать только auth_request , например:
location = /upload { auth_request /upload/authenticate; ... } location = /upload/authenticate { internal; proxy_set_body off; proxy_pass http://backend; }
Предварительная загрузка логики аутентификации защищает от неавторизованных запросов независимо от начального размера длины заказа POST.