Ответ нашел неожиданно. Может быть кому-то пригодится, поэтому напишу его здесь.
У меня на сайте есть форма Ajax загрузки фотографий — немного переделанный
github.com/valums/file-uploader/. Устанавливал я его, когда он был еще в версии 0.x.
Пишет мне мне посетитель сайта — у него не загружаются фотографии через эту форму. Выясняю, браузер Опера. Проверил — у меня все загружается. Прошу прислать фотографии. Прислал, действительно не загружается.
Полез в логи, смотрю а там такое:
*.*.*.* - - [28/Jan/2013:23:06:55 +0400] "яШяа\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00яю\x00;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 75" 400 0 "-" "-"
*.*.*.* — мой IP адрес.
Реализация отправки файла через XMLHttpRequest была реализована следующим образом:
xhr.open("POST", queryString, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.send(file);
Здесь file — объект типа
File
До конца не разобрался, но похоже на определенных файлах Opera рвет тело запроса. И сервер воспринимает один запрос от нее как два невалидных запроса в одно открытое соединение.
Переделал блок отправки фала. Сделал так:
xhr.open("POST", queryString, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
if (typeof FormData != 'undefined') {
var formData = new FormData();
formData.append('imgfile', file);
file = formData;
} else {
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
if(typeof file.type != 'undefined' && file.type.length) {
xhr.setRequestHeader("X-Mime-Type", file.type);
}
xhr.setRequestHeader("Cache-Control", "no-cache");
}
xhr.send(file);
Все заработало.
PS valums/file-uploader дорос уже до версии
3.2 (и даже переименовался), но как пишет сам разработчик, он отказался от поддержки Оперы. Так что, возможно, эта проблема актуальна и в текущей версии.