У меня довольно распространенная проблема, и я часами читал кое-что об этом, но мне не удается ее исправить, и я схожу с ума ...
Контекст
У меня есть веб-сайт , где пользователи могут загрузить изображение на мой сервер (в общем случае из браузера iOS / Safari). Страница с формой загрузки: эта .
Бэкэнд сделан с PHP (без фреймворка). Фронт-эндом является HTML / Javascript. Это довольно старый сайт, который я сделал в 2010 году, так что это не «супер секси»! : -)
Я сделал журналы для мониторинга результатов загрузки, и я вижу, что около 30% пользовательских загрузок не удалось ... Я думаю, это не обычно!
Эти ошибки происходят из 2 источников (один и тот же пользователь, пытающийся загрузить несколько раз, может иметь сочетание этих 2 источников):
$_FILES['myFormFieldName']
равно NULL
$_FILES['myFormFieldName']
НЕДЕЙСТВИТЕЛЕН, но $_FILES['myFormFieldName']['error']
равен 3 (UPLOAD_ERR_PARTIAL
) с $_FILES['xxx']['tmp_name']
и $_FILES['xx']['type']
пустым, а $_FILES['xxx']['size']
равен "0"
Эти ошибки не являются детерминированными ...
- Когда я тестирую себя (используя то же изображение, что и у пользователя, у которого проблемы с загрузкой), у меня нет проблем
- В своих журналах я вижу, что у некоторых пользователей всегда возникают проблемы с загрузкой, а у других - нет.
- Я также вижу, что некоторым пользователям, у которых возникли проблемы, удалось загрузить свой файл с помощью siccess после нескольких попыток
- У меня был контакт с одним пользователем, у которого возникли проблемы с сообщением о том, что у него появляется страница с ошибкой
Safari cannot open the page because network connection was lost
от Safari при попытке загрузить его изображение (всякий раз, когда он использует данные WiFi или мобильный 3G / 4G)
Код
HTML-форма для загрузки файла
(ограничить загрузку пользователем 35M со стороны клиента)
<ul class="pageitem">
<form name="empty-custom-native"
enctype="multipart/form-data"
action="/upload.php?method=nativeUpload"
method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="36700160" />
<li class="button" >
<input type="file" name="iosImageFILE" id="iosImageFILE"/>
</li>
</form>
<li class="button directUrlButton" onclick="javascript:onclickNativeUploadForm();">
<input type="button" value="Upload" />
</li>
</ul>
Javascript, вызываемый HTML
(используется для проверки того, что входной файл не пустой перед отправкой формы)
function onclickNativeUploadForm(){
if( document.getElementById('iosImageFILE').value=="" ){
alert("Please choose an image FIRST !");
} else{
showPleaseWait();
setTimeout(submitNativeUploadForm, 2000);
}
}
function submitNativeUploadForm(){
document.forms['empty-custom-native'].submit();
}
PHP-код, управляющий загрузкой (извлечением) файла
<?php
if( isset($_FILES['iosImageFILE']) && !empty($_FILES['iosImageFILE']) ){
$uploadStatus = $_FILES['iosImageFILE']['error'];
if( $uploadStatus==0 ){
// Copy source file to temp file
if( !move_uploaded_file($_FILES['iosImageFILE']['tmp_name'], $_SERVER['DOCUMENT_ROOT']."/".$userImageTemp) ) {
throw new Exception("fileUploadCopy");
}
} else{
if( $uploadStatus==1 ){ throw new Exception("fileUploadIniSize"); }
else if( $uploadStatus==2 ){ throw new Exception("fileUploadFormSize"); }
else if( $uploadStatus==3 ){ throw new Exception("fileUploadPartial"); } // THIS ERROR ...
else if( $uploadStatus==4 ){ throw new Exception("fileUploadNoFile"); }
else if( $uploadStatus==6 ){ throw new Exception("fileUploadNoTmpDir"); }
else if( $uploadStatus==7 ){ throw new Exception("fileUploadCantWrite"); }
else if( $uploadStatus==8 ){ throw new Exception("fileUploadExtension"); }
else{
throw new Exception("fileUploadSystem");
}
}
} else{
throw new Exception("fileUploadUpload"); // ... OR THIS ERROR
}
// If anything was OK, we continue here with the uploaded file copied in our working dir to do some stuff with it...
?>
Так что в моем случае у меня есть fileUploadUpload
или fileUploadPartial
исключений.
Исследования
Серверная часть (конфигурация php.ini)
Я проверил переменные среды PHP, относящиеся к загрузке файлов (с помощью команды ini_get
), чтобы убедиться, что я не превысил максимальный размер файла или максимальное количество загрузок.
Все вроде нормально, у меня довольно щедрые ограничения, post_max_size
лучше, чем upload_max_filesize
. upload_tmp_dir
пусто, наверное, это означает, что я использую систему по умолчанию /tmp
dir?
Скажите, если вы видите проблемы или другие вещи, которые нужно проверить.
Примечание. У меня нет доступа к php.ini
, но эти значения фиксируются моим хостинг-провайдером (я использую виртуальный хостинг).
file_uploads : '1'
upload_tmp_dir : ''
upload_max_filesize : '128M'
max_file_uploads : '20'
post_max_size : '130M'
max_execution_time : '300'
Клиентская часть (код HTML / JS)
MAX_FILE_SIZE
меньше максимального размера файла, разрешенного моим сервером PHP.
Я использовал enctype="multipart/form-data"
и method="post"
, как и ожидалось.
Я не делаю выгрузку файлов AJAX, просто использую Javascript для проверки пустоты входного файла перед отправкой формы с помощью JS.
Серверная часть (код PHP)
Когда я отлаживаю содержимое $_FILES['iosImageFILE']
, я получаю это для ошибки fileUploadPartial
(а для ошибки fileUploadUpload
это ноль).
iosImageFILE = {"name":"DD292A1C-9CBF-4843-9E1C-7C815593C67A.png","type":"","tmp_name":"","error":3,"size":0}
Серверная часть (файловая система)
Я пытался проверить каталог /tmp
, где должны находиться загруженные файлы, но у меня нет к нему доступа. Я хотел бы проверить, что он не «полон старых файлов tmp», но, думаю, нет.
На самом деле я создал PHP-скрипт для сканирования его содержимого с использованием var_export(scandir('/tmp'))
, и я вижу только некоторые sess_xxxxx
файлы сеансов (около 7000 файлов).
Обновление кода
Я обновил и улучшил свой веб-сайт до https (ранее не был защищенным http) и обновил версию PHP с 5.6 до 7.0). Без каких-либо изменений при загрузке файлов.
Брандмауэр?!?
Возможно, я подозреваю, что проблема с брандмауэром у моего хостинг-провайдера (я читал, что он может блокировать некоторые вещи при загрузке файлов ...).
Но мне сказали, что на моем хосте не активирован брандмауэр ...
Заключение
Я действительно не знаю, что делать дальше, чтобы исследовать и найти эту проблему.
Обратите внимание, что почти все, кто загружает файлы, приходят из браузера iOS / Safari.Я не знаю, будут ли такие же проблемы с другими ОС или браузерами ...
Я - веб-разработчик внешнего интерфейса, и я должен сообщить, что меня не устраивает такая проблема.
Любая помощь приветствуется!