Добавление заголовка Content-Encoding к загруженным файлам с подписанным URL - PullRequest
0 голосов
/ 06 января 2019

Мне нужно загрузить Gziped-контент на S3 через подписанный URL.

Вот как я генерирую подписанный URL с помощью JS-сервера:

s3.createPresignedPost({
  Bucket: 'name',
  Fields: {
    key: 'key'
  }
})

Я попытался передать заголовок Content-Encoding подписанному запросу POST, но это не сработало. Заголовки неправильно установлены на объекте s3.

Я также попытался настроить лямбду пост-загрузки для обновления метаданных. Не удалось с ошибкой File is identical error

Наконец, я попытался использовать cloudfront + лямбду для форсирования заголовка. Это также не удалось с ошибкой, указывающей, что Content-Enconding является защищенной ошибкой.

1 Ответ

0 голосов
/ 07 января 2019

- запуск обновления -

Для загрузки на S3 через Ajax или JS-скрипты я бы посоветовал использовать метод s3.getSignedUrl. s3.createPresignedPost предназначен только для прямой загрузки через браузер.

Ниже приведен пример загрузки Ajax jQuery, которую я создал с помощью этого руководства.

s3.getSignedUrl('putObject', {
    Bucket: 'bucketName',
    Key: 'sample.jpg.gz',
    // This must match with your ajax contentType parameter
    ContentType: 'binary/octet-stream'
    /* then add all the rest of your parameters to AWS puttObect here */
  }, function (err, url) {
    console.log('The URL is', url);
  });

Ajax PUT Script - возьмите вызов функции Url сверху и используйте его ниже.

$.ajax({
    type: 'PUT',
    url: "https://s3.amazonaws.com/bucketName/sample.jpg.gz?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Content-Type=binary%2Foctet-stream&Expires=1547056786&Signature=KyTXdr8so2C8WUmN0Owk%2FVLw6R0%3D",
    //Even thought Content-Encoding header was not specified in signature, it uploads fine.
    headers: {
        'Content-Encoding': 'gzip'
    },
    // Content type must much with the parameter you signed your URL with
    contentType: 'binary/octet-stream',
    // this flag is important, if not set, it will try to send data as a form
    processData: false,
    // the actual file is sent raw
    data: theFormFile
}).success(function () {
    alert('File uploaded');
}).error(function () {
    alert('File NOT uploaded');
    console.log(arguments);
});

В объекте S3 вы должны увидеть Content-Type, Content-Encoding под метаданными.

Важное замечание Когда вы пытаетесь загрузить с помощью JS-скриптов, которые работают в браузерах, обычно браузеры, как правило, перед отправкой метода PUT обычно отправляют предварительный просмотр метода OPTIONS (или проверку CORS). Вы получите ошибку 403 Forbidden для ОПЦИЙ, поскольку CORS на корзине S3 этого не позволяет. Один из способов, который я решил, заключается в использовании следующей конфигурации CORS на уровне сегмента. Ссылка

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

- конец обновления -

Ты пробовал вот так? Я только что проверил политику, используя образец html , приведенный в документации AWS. Справка - https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html

s3.createPresignedPost({
  Bucket: 'name',
  Conditions: [
    { "Content-Encoding": "gzip" }
  ],
  Fields: {
    key: 'key'
  }
})

Обновление - Вот мое наблюдение до сих пор.

Нам действительно нужно проверить ваш клиент, который выполняет операцию загрузки. Если вы хотите установить Content-Encoding в MetaData, то в вашем предварительно подписанном URL-адресе должно быть установлено свойство Content-Encoding. Если в подписанном URL-адресе его нет, а в заголовке запроса - Extra input fields: content-encoding.

Я подписал URL-адрес с помощью Content-Encoding и загрузил заархивированный файл со следующим примером html.

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
  <body>
  <form action="http://bucket-name.s3.amazonaws.com" method="post" enctype="multipart/form-data">
    Key to upload: 
    <input type="input"  name="key" value="sample.jpg.gz" /><br />
    Content-Encoding: 
    <input type="input"  name="Content-Encoding" value="gzip" /><br />
    <input type="text"   name="X-Amz-Credential" value="AKIAIOSFODNN7EXAMPLE/20190108/us-east-1/s3/aws4_request" />
    <input type="text"   name="X-Amz-Algorithm" value="AWS4-HMAC-SHA256" />
    <input type="text"   name="X-Amz-Date" value="20190108T220828Z" />
    Tags for File: 
    <input type="hidden" name="Policy" value='bigbase64String' />
    <input type="hidden" name="X-Amz-Signature" value="xxxxxxxx" />
    File: 
    <input type="file"   name="file" /> <br />
    <!-- The elements after this will be ignored -->
    <input type="submit" name="submit" value="Upload to Amazon S3" />
  </form>
</html>

Если я не отправляю заголовок Content-Encoding, выдается ошибка Policy Condition failed: ["eq", "$Content-Encoding", "gzip"]

Примечание - Если при загрузке вы используете https, убедитесь, что у вас есть соответствующий сертификат на конечной точке S3, в противном случае вы получите сертификаты об ошибках.

S3 Скриншот. enter image description here

...