Невозможно загрузить файлы с ACL для публичного чтения в пространства Digital Ocean.

Я пытаюсь загрузить изображения в пространство Digital Ocean из браузера. Эти изображения должны быть общедоступными. Я могу успешно загрузить изображения.

Однако, хотя ACL установлен на public-read, загруженные файлы всегда являются личными.

Я знаю, что они частные, потому что а) на приборной панели указано, что разрешения являются «частными», и б) потому, что общедоступные URL-адреса не работают, и в) ручное изменение разрешений на «общедоступные» на приборной панели все исправляет.

Вот общий процесс, который я использую.

  1. Создайте предварительно подписанный URL-адрес на бэкэнде
  2. Отправьте этот URL в браузер
  3. Загрузите изображение на этот предварительно подписанный URL

Есть идеи, почему изображения не публикуются?

Код

Следующие примеры написаны на TypeScript и используют SDK AWS v3.

Бэкэнд

Это создает предварительно подписанный URL-адрес для загрузки файла.

      import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

const client = new S3Client({
    region: 'nyc3',
    endpoint: 'https://nyc3.digitaloceanspaces.com',
    credentials: {
        accessKeyId: process.env.DIGITAL_OCEAN_SPACES_KEY,
        secretAccessKey: process.env.DIGITAL_OCEAN_SPACES_SECRET,
    },
})

const command = new PutObjectCommand({
    ACL: 'public-read',
    Bucket: 'bucket-name',
    Key: fileName,
    ContentType: mime,
})

const url = await getSignedUrl(client, command)

Затем предварительно подписанный URL-адрес отправляется в браузер.

Внешний интерфейс

Это код на клиенте для фактической загрузки файла в Digital Ocean. fileявляется файловым объектом .

      const uploadResponse = await fetch(url, {
    headers: {
        'Content-Type': file.type,
        'Cache-Control': 'public,max-age=31536000,immutable',
    },
    body: file,
    method: 'PUT',
})

Метаданные

  • AWS SDK: 3.8.0

3 ответа

Решение

Оказывается, для Digital Ocean также необходимо установить public-read ACL в качестве заголовка в запросе на размещение.

      //front-end
const uploadResponse = await fetch(url, {
    headers: {
        'Content-Type': file.type,
        'Cache-Control': 'public,max-age=31536000,immutable',
        'x-amz-acl': 'public-read', // add this line
    },
    body: file,
    method: 'PUT',
})

У меня нет репутации, чтобы комментировать, поэтому добавляю ответ. Спасибо, @Nick ... это один из немногих рабочих примеров кода, который я видел для предварительно подписанного URL-адреса DigitalOcean. Хотя в официальном описании DigitalOcean здесь упоминается Content-Typeнеобходим для загрузки с предварительно подписанными URL-адресами, пример кода отсутствует .

Еще одна ошибка, из-за которой мне не удалось загрузить файл, используя предварительно подписанные URL-адреса в DigitalOcean, заключалась в использовании 'Content-Type':'multipart/form-data' а также FormData().

Увидев этот пост, я последовал предложению @Nика использовать File() объект и 'Content-Type':'<relevant_mime>'. Затем загрузка файла прошла отлично. Это также не рассматривается в официальных документах.

Попробуйте сделать это, чтобы сделать ACL общедоступным в Digital Ocean Spaces:

      s3cmd --access_key=YOUR_ACCESS_KEY --secret_key=YOUR_SECRET_KEY --host=YOUR_BUCKET_REGION.digitaloceanspaces.com --host-bucket=YOUR_BUCKET_NAME.YOUR_BUCKET_REGION.digitaloceanspaces.com --region=YOUR_BUCKET_REGION setacl s3://YOUR_BUCKET_NAME --acl-public
Другие вопросы по тегам