19

I've got several objects stored in Amazon S3 whose content-type I need to change from text/html to application/rss+xml. I gather that it should be possible to do this with a copy command, specifying the same path for the source and destination. I'm trying to do this using the AWS cli tools, but I'm getting this error:

$ aws s3 cp s3://mybucket/feed/ogg/index.html \
            s3://mybucket/feed/ogg/index.html \
            --content-type 'application/rss+xml'
copy failed: s3://mybucket/feed/ogg/index.html
to s3://mybucket/feed/ogg/index.html
A client error (InvalidRequest) occurred when calling the
CopyObject operation: This copy request is illegal because it is
trying to copy an object to itself without changing the object's
metadata, storage class, website redirect location or encryption
attributes.

If I specify a different path for source and destination, I don't get the error:

$ aws s3 cp s3://mybucket/feed/ogg/index.html \
            s3://mybucket/feed/ogg/index2.html \
            --content-type 'application/rss+xml'
copy: s3://mybucket/feed/ogg/index.html
to s3://mybucket/feed/ogg/index2.html

Even though the command completes successfully, the index2.html object is created with the text/html content type, not the application/rss+xml type that I specified.

How can I modify this command-line to make it work?

veben
  • 8,680
  • 11
  • 48
  • 57
nelstrom
  • 17,106
  • 12
  • 51
  • 65
  • 1
    Just saw [this issue](https://github.com/aws/aws-cli/issues/652#issuecomment-41213226) reporting the same problem. That thread includes a couple of workarounds, so I'll see how I get on with them. – nelstrom May 08 '14 at 20:48

3 Answers3

13

It's possible to use the low level s3api to make this change:

$ aws s3api copy-object --bucket archive --content-type "application/rss+xml" \
    --copy-source archive/test/test.html --key test/test.html \
    --metadata-directive "REPLACE"

http://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html

The problem was just not being able to specify the --metadata-directive. Thanks for pointing out the open issue / feature request, nelstrom!

Cawb07
  • 1,739
  • 3
  • 13
  • 21
  • How can this be executed for several objects with a certain extension? – bart Dec 11 '16 at 02:56
  • 1
    There may be a cleaner way, but you could list the object in a file then read all the lines and execute the above command on each line, so the above would look like: `while read line; do copy-object --bucket archive --content-type "application/rss+xml" --copy-source archive/$line.html --key $line.html --metadata-directive "REPLACE"; done < objects.txt` – Cawb07 Dec 12 '16 at 22:25
5

You can also do it with the higher level API, by copying a file over itself but marking it as a change in metadata:

aws s3 cp \
  --content-type "application/rss+xml" \
  --metadata-directive REPLACE \
  s3://mybucket/myfile \
  s3://mybucket/myfile 
Malvineous
  • 20,120
  • 14
  • 99
  • 121
0

You can override the content-type of your file, with the aws s3 cp command, using the --metadata-directive optional attribute to specify the content-type is replaced with the one provided with --content-type 'application/rss+xml' during the copy:

aws s3 cp \
--content-type 'application/rss+xml' \
--metadata-directive REPLACE \
s3://mybucket/feed/ogg/index.html \
s3://mybucket/feed/ogg/index.html

More information: https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html

Then, you can verify it by checking the file metadata:

aws s3api head-object \
--bucket mybucket \
--key feed/ogg/index.html
veben
  • 8,680
  • 11
  • 48
  • 57