Вопрос или проблема
Я работаю над проектом под названием “Автоматическая система учета лиц”, которая будет распознавать лицо пользователя, отображать информацию о пользователе и сохранять захваченное изображение на локальном сервере.
Процесс выглядит так:
пользователь сканирует изображение с помощью веб-камеры -> система сопоставляет сканированное лицо пользователя с моделями -> получает данные пользователя с помощью JSON -> сохраняет захваченное изображение на сервере, используя JSON.
Проблема в том, что я включил SSL в Laragon и использую HTTPS для улучшения производительности моего проекта, и всё работает, кроме функции “сохранить захваченное изображение”. Но если я отключаю SSL и использую только HTTP, функция “сохранить захваченное изображение” работает нормально и сохраняет захваченные изображения в хранилище сервера.
Вот код:
js:
async function saveImageToServer(imageBlob, label) {
const formData = new FormData();
formData.append("image", imageBlob, "capturedImg.png");
formData.append("label", label);
try {
const response = await fetch("/api/saveImage", {
method: "POST",
headers: {
"CSRF-TOKEN": csrfToken,
},
body: formData,
});
if (response.ok) {
const data = await response.json();
if (data.imageUrl) {
displayImageOnCanvas(data.imageUrl);
console.log("Изображение сохранено и отображено на холсте");
} else {
console.error("Ответ не содержал imageUrl:", data);
}
} else {
const errorData = await response.json();
console.error("Не удалось сохранить изображение:", errorData);
}
} catch (error) {
console.error("Ошибка при сохранении изображения:", error);
}
}
контроллер
public function storeImage(Request $request)
{
if ($request->hasFile('image') && $request->input('label')) {
$timestamp = getCurrentDate();
Session::put('current_date', $timestamp);
$image = $request->file('image');
$kodePegawai = $request->input('label');
// Убедитесь, что каталог загрузки существует
$uploadDir="labels/" . $kodePegawai . '/capturedImg/';
Storage::disk('public')->makeDirectory($uploadDir);
$imageName = $kodePegawai . $timestamp . '.png';
$path = $image->storeAs($uploadDir, $imageName, 'public');
if ($path) {
$imageUrl = asset('storage/' . $uploadDir . $imageName);
return response()->json(['imageUrl' => $imageUrl]);
} else {
return response()->json(['error' => 'Сервер не смог сохранить изображение'], 500);
}
} else {
return response()->json(['error' => 'Изображение или метка не получены'], 400);
}
}
результат:
POST https://indodacin.test/api/saveImage 419
saveImageToServer @ script.js:261
(anonymous) @ script.js:197
setInterval
startFaceDetection @ script.js:142
await in startFaceDetection
(anonymous) @ script.js:59 Понять эту ошибку
script.js:282 Ошибка при сохранении изображения: SyntaxError: Unexpected token '<', "<!DOCTYPE "... недопустимый JSON
Я пробовал много решений из других тем, спрашивал у GPT, что не так, и ни одно из их решений не сработало. Вот что я пробовал:
- проверить и обновить права на хранилище
- проверить CSRF-токен
- использовать путь, который был указан в хранилище сервера и т. д.
Ответ или решение
Проблема, с которой вы столкнулись при попытке сохранить захваченное изображение с веб-камеры через HTTPS в Laravel 11, может быть связана с несколькими факторами. Давайте рассмотрим, вероятные причины и пути их решения.
1. Ошибка 419 – CSRF-токен
Ошибка 419 обычно указывает на проблему с проверкой CSRF-токена. При использовании HTTPS убедитесь, что вы правильно передаете CSRF-токен в заголовках запроса. Проверьте, правильно ли вы его получаете на клиенте.
Пример получения токена в JavaScript:
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
Убедитесь, что в вашем HTML-документе есть мета-тег:
<meta name="csrf-token" content="{{ csrf_token() }}">
2. Корректный путь
Следует убедиться, что вы используете правильный путь для отправки POST-запроса. Попробуйте использовать полный путь с учетом домена при вызове fetch()
.
3. Ответ сервера не в формате JSON
Ошибка Unexpected token '<', "<!DOCTYPE "... is not valid JSON
говорит о том, что ответ от сервера не является корректным JSON. Это часто происходит, когда сервер возвращает HTML-документ (например, страницу ошибки). Проверьте, что происходит на стороне сервера, когда выполняется запрос.
Рекомендации:
- Проверьте файл
storage/logs/laravel.log
на наличие ошибок, которые могут более подробно объяснить причину сбоя. - Используйте инструменты разработчика вашего браузера (например, вкладка "Сеть") для проверки, что именно возвращает сервер при выполнении запроса.
4. Настройки CORS
При работе с HTTPS важно убедиться, что ваши настройки CORS (Cross-Origin Resource Sharing) настроены правильно. Если ваш фронтенд и бэкенд находятся на разных поддоменах или портах, это может вызвать проблемы.
Пример настройки CORS в Laravel:
В файле app/Http/Middleware/HandleCors.php
убедитесь, что указаны необходимые заголовки:
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Content-Type, X-Auth-Token, Origin, Authorization, X-CSRF-TOKEN');
}
5. Проверьте права на папку хранения
Проблема также может заключаться в недостаточных правах на записи в директории storage
. Убедитесь, что сервер имеет права на запись в эту папку:
chmod -R 775 storage
Или установите владельца на пользователя, под которым запущен ваш веб-сервер (например, www-data
для Apache или Nginx):
chown -R www-data:www-data storage
Заключение
Пожалуйста, проверьте все предложенные рекомендации шаг за шагом. Это должно помочь вам выявить и решить проблему с сохранением изображений при использовании HTTPS в Laravel 11. Если ни один из этих шагов не помог, рассмотрите возможность тестирования проекта в локальной среде без SSL, а затем добавления HTTPS после того, как основная функциональность будет проверена и отлажена.