Ошибка CORS при вызовах Azure Storage из Javascript для подтверждения загруженных фрагментов

Вопрос или проблема

Я хочу, чтобы пользователи загружали огромные файлы непосредственно в Azure Storage. У меня есть веб-приложение на Flask Python, но я не хочу, чтобы файл загружался на мой веб-сервер из-за ограничений по размеру.

Когда пользователь выбирает файл для загрузки и нажимает кнопку загрузки, происходит следующее:

  1. Вызывается API, который генерирует URL SAS и имя блоба для файла, который нужно загрузить. Код, генерирующий оба значения:
    blob_name = str(uuid.uuid4())  

    container_name = os.environ[default_container_name_setting]

    sas = generate_blob_sas(account_name=service.account_name,
                            account_key=access_key,
                            container_name=container_name,
                            blob_name=blob_name,
                            permission=BlobSasPermissions(write=True, read=True, create=True),
                            expiry=datetime.utcnow() + timedelta(hours=2)) 

    sas_url="https://" + service.account_name + '.blob.core.windows.net/' + container_name + "https://stackoverflow.com/" + blob_name + '?' + sas
    return sas_url, blob_name
  1. Файл затем загружается по частям:
const chunkSize = 1024 * 1024 * 20; 
const totalChunks = Math.ceil(file.size / chunkSize);
const blockIds = []; // Массив для хранения идентификаторов блоков

for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);
    const blockId = btoa("block-" + i); // Кодирование идентификатора блока в base64
    blockIds.push(blockId);

    // Загрузка каждой части
    const uploadResponse = await fetch(sas_url + "&comp=block&blockid=" + blockId, {
        method: "PUT",
        headers: {
            "x-ms-blob-type": "BlockBlob",
            "Content-Type": file.type
        },
        body: chunk
    });

    if (!uploadResponse.ok) {
        return false;
    }
}

На этом этапе всё работает. Однако следующий шаг — сказать Azure соединить части:

const commitResponse = await fetch(sas_url + "&comp=commitBlockList", {
    method: "PUT",
    headers: {
        "Content-Type": "application/xml",
        "x-ms-version": "2020-10-02",
        "Content-Length": "0"
    },
    body: `<BlockList>${blockIds.map(id => `<Latest>${id}</Latest>`).join('')}</BlockList>`
});

if (!commitResponse.ok) {
    throw new Error("Не удалось подтвердить блоки блоба.");
}

В этот момент у меня всегда возникает ошибка CORS:

Доступ к fetch по адресу ‘https://xxx.blob.core.windows.net/container/e07d13fa-bcd6-45cf-9eea-3295e17dc567?se=2024-11-01T04%2A18%3B30Q&sp=rcw&sv=2024-11-04&sr=b&sig=CudrFGsJ1HGnYo6Bh3K7WVAabgdOAsPteWq47XKuKDI%3D&comp=commitBlockList’ из источника ‘http://localhost:4449’ заблокирован политикой CORS: Ответ на предварительный запрос не проходит проверку контроля доступа: В заголовке ‘Access-Control-Allow-Origin’ нет разрешенного ресурса. Если прозрачный ответ соответствует вашим потребностям, установите режим запроса на ‘no-cors’, чтобы получить ресурс с отключенным CORS.

Я знаю, что правильно настроил CORS в Azure Storage, потому что часть загрузки работает.

На вкладке Blob Service я добавил свой localhost-источник с разрешенными методами GET, POST, OPTIONS и PUT.

Я пробовал снова сгенерировать URL SAS с полученным именем Blob, но я всё еще получаю ошибку CORS.

Что я упускаю?

Ответ или решение

Ошибка CORS при вызовах Azure Storage из JavaScript для завершения загрузок чанками

Когда вы работаете с загрузками файлов в Azure Storage через JavaScript, особенно с использованием ссылок SAS (Shared Access Signature), вы можете столкнуться с ошибкой CORS (Cross-Origin Resource Sharing). Эта ошибка возникает, когда браузер блокирует запрос к ресурсу с другого домена из-за политик безопасности. Давайте подробно разберем вашу ситуацию и предложим возможные решения.

Описание проблемы

Вы реализуете upload больших файлов в Azure Storage без передачи данных через свой Flask-сервер. Совершенно логично, что такой подход позволяет избежать проблем с исчерпанием ресурсов сервера. Ваш текущий процесс загружает файл в чанках, а затем вызывает метод commitBlockList для объединения загруженных чанков. Однако на этапе вызова commitBlockList вы получаете ошибку CORS:

Access to fetch at 'https://xxx.blob.core.windows.net/...' from origin 'http://localhost:4449' has been blocked by CORS policy.

Настройка CORS в Azure Storage

Вы упомянули, что правильно настроили CORS в Azure Storage, добавив свой localhost в список разрешенных источников с методами GET, POST, OPTIONS и PUT. Это правильный подход, но убедитесь, что все настройки CORS действительно применены. Важные моменты, которые стоит проверить:

  1. Убедитесь в корректности домена: Проверьте, что вы используете точно такое же значение для домена в настройках CORS. Иногда лишние символы или пробелы могут вызвать проблемы.

  2. Правильность методов: Убедитесь, что вы добавили метод OPTIONS в список разрешенных методов. Хотя это часто делается автоматически, иногда дополнительные настройки могут не сохраняться.

  3. Параметры заголовков: Проверьте настройки заголовков. Часто полезно разрешить заголовки Content-Type и x-ms-blob-type, чтобы избежать проблем с запросами, используя дополнительные параметры.

Диагностика и отладка

Для отладки ошибок CORS выполните следующие шаги:

  1. Проверьте ответы на предзапросы: Используйте инструменты разработчика в вашем браузере, чтобы проанализировать сетевые запросы. Убедитесь, что запросы OPTIONS выполняются успешно, и Azure отвечает с правильными заголовками CORS.

  2. Сравните разные методы запроса: Проверьте, как CORS обрабатывается при вызове PUT на этапе загрузки чанков и при вызове commitBlockList. Если предзапрос для commitBlockList возвращает ошибку, это и вызывает основную проблему.

  3. Тестируйте на других доменах: Если возможно, протестируйте код на другом домене, чтобы понять, является ли проблема специфичной для localhost.

Альтернативные подходы

Если все вышеперечисленные шаги не решают проблему, рассмотрите возможность использования другого клиентского подхода:

  1. Согласно подходу no-cors: Возможно, вам стоит установить режим запроса в no-cors, но будьте осторожны: в этом режиме браузер не возвращает данные о статусе ответа. Это может быть полезно только для тестирования, и не рекомендуется для выполнения окончательных бизнес-логик.

  2. Использование Azure Functions: Рассмотрите возможность использования Azure Functions для обработки запросов. Функции могут служить промежуточным звеном между вашим клиентом и Azure Storage, управляя CORS настройками более гибко.

  3. Серверный подход: Если всё ещё возникают сложности, возможно, стоит временно переключиться на загрузку через сервер, чтобы проверить, действительно ли проблема в CORS.

Заключение

Ошибка CORS при работе с Azure Storage может быть вызвана рядом факторов, включая неверную настройку на стороне Azure и характеристики самого запроса. Проведите тщательную проверку всех настроек и используйте подходы для диагностики. Наконец, допускайте возможность использования промежуточных решений, пока не будет принято окончательное решение.

Постоянный анализ и улучшения в вашем процессе загрузки помогут избежать подобных ситуаций в будущем и сделают ваш проект более устойчивым и удобным для пользователей.

Оцените материал
Добавить комментарий

Капча загружается...