S3: Set Content-type metadata on save

Issue #210 new
trikosuave created an issue

I didn't see anything in the documentation. Is it possible to set the content-type in the Metadata in S3? I am saving an xml file to our bucket and would like it to display in the browser, instead of automatically downloading the file.


Comments (5)

  1. trikosuave reporter

    It defaults to binary/octet-stream. I would like to change it to text/plain. I replace the file daily so making this change manually wouldn't be an option. Thanks again!

  2. Gordon NA

    How are you creating the file?

    Verify you are using the s3boto storage. It should guess the correct mimetype for properly labelled files (line 159 or line 401)

    If you are using the save method, you can specify the content_type attribute on the File object you pass and it will use that value.

  3. trikosuave reporter

    I am using s3boto. I am not using the save method because I am not using a model. I am simply running a query and running the data through a template to create an xml file and saving it to s3. Is there a way to use the save method without creating an instance of a class?

        file_name = 'myfile.xml'
        xml_file = default_storage.open(file_name, 'w')

    Otherwise, I have to copy a file onto itself and set the content type in the process (seems wasteful):

            s3 = boto.connect_s3()
            bucket = s3.get_bucket(my_bucket)
            if bucket:
                key = bucket.get_key(file_name)
            if key:
                key.copy(key.bucket, key.name, preserve_acl=True,
                         metadata={'Content-Type': 'application/xml'})

    I realize I could just do it all with boto, but I want to use default storage so it acts differently in dev/test than in production (default storage is set to local in debug mode).


  4. Gordon NA

    Check and make sure the version of django-storages you're using sets the content type like the two lines I linked previously. Maybe this is an issue with your version?

    If you want to write the file directly (I think you do) you should verify mimetypes.guess_type("myfile.xml") returns the mimetype you are expecting. If it doesn't you should initialize it with the response you want. (see https://docs.python.org/2/library/mimetypes.html#mimetypes.add_type) Keep in mind that mimetypes uses the file extension for determined the mimetype... so if your "myfile.xml" is actually "myfile-xml.not-guessable" then it will not work. You will need to use the _save() method in this case.

    Something like the following in your settings.py would do the trick

    import mimetypes
    mimetypes.add_type("application/xml", ".xml", True)

    But to answer your other question, storage save and model save are different. https://docs.djangoproject.com/en/1.7/ref/files/storage/#django.core.files.storage.Storage.save

    If you want to use storage.save and force the file name then you can use _save https://docs.djangoproject.com/en/1.7/howto/custom-file-storage/#django.core.files.storage._save

    You can force the content type in the _save method by setting the content_type attribute on the file object you pass in. See https://bitbucket.org/david/django-storages/src/f153a70ba254dc129d9403546809a02256ef75b5/storages/backends/s3boto.py?at=default#cl-400

  5. Алексей Стрелков

    I still cannot find a solution, guess_type returns image/jpeg for jpgs in my case, but the resulting content-type on s3 is still octet/stream

  6. Log in to comment