Popularity
3.2
Declining
Activity
0.0
Stable
9
4
0

Description

Creating a properly encoded and escaped standards-compliant HTTP Content-Disposition header for potential filenames with special characters is surprisingly confusing.

This ruby gem does that and only that, in a single 50-line file with no dependencies.

Crystal port of https://github.com/shrinerb/content_disposition

Programming language: Crystal
License: MIT License
Tags: HTTP     Web Frameworks     Tools    
Latest version: v1.1.3

ContentDisposition alternatives and similar shards

Based on the "HTTP" category.
Alternatively, view ContentDisposition alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of ContentDisposition or a related project?

Add another 'HTTP' Shard

README

content_disposition.cr

Build Status GitHub release GitHub license

Creating a properly encoded and escaped standards-compliant HTTP Content-Disposition header for potential filenames with special characters is surprisingly confusing.

This library does that and only that, in a single 50-line file with no dependencies.

Crystal port of https://github.com/shrinerb/content_disposition

Content-Disposition header

Before we proceed with the usage guide, first a bit of explanation what is the Content-Disposition header. The Content-Disposition response header specifies the behaviour of the web browser when opening a URL.

The inline disposition will display the content "inline", which means that known MIME types from the Content-Type response header are displayed inside the browser, while unknown MIME types will be immediately downloaded.

Content-Disposition: inline

The attachment disposition will tell the browser to always download the content, regardless of the MIME type.

Content-Disposition: attachment

When the content is downloaded, by default the filename will be last URL segment. This can be changed via the filename parameter:

Content-Disposition: attachment; filename="image.jpg"

To support old browsers, the filename should be the ASCII version of the filename, while the filename* parameter can be used for the full filename with any potential UTF-8 characters. Special characters from the filename need to be URL-encoded in both parameters.

Installation

  1. Add the dependency to your shard.yml:
   dependencies:
     content_disposition:
       github: jetrockets/content_disposition
  1. Run shards install

Usage

require "content_disposition"

ContentDisposition.format(disposition: "inline", filename: "racecar.jpg")
# => "inline; filename=\"racecar.jpg\"; filename*=UTF-8''racecar.jpg"

A proper content-disposition value for non-ascii filenames has a pure-ascii as well as an ascii component. By default the filename will be turned into ascii by replacing any non-ascii chars with '?' (which is then properly percent-escaped to %3F in output).

ContentDisposition.format(disposition: "attachment", filename: "råcëçâr.jpg")
# => "attachment; filename=\"r%3Fc%3F%3F%3Fr.jpg\"; filename*=UTF-8''r%C3%A5c%C3%AB%C3%A7%C3%A2r.jpg"

But you can pass in your own proc to do it however you want.

ContentDisposition.format(
  disposition: "attachment",
  filename: "råcëçâr.jpg",
  to_ascii: ->(filename : String) { String.new(filename.encode("US-ASCII", invalid: :skip)) }
)
# => "attachment; filename=\"racecar.jpg\"; filename*=UTF-8''r%C3%A5c%C3%AB%C3%A7%C3%A2r.jpg"

You can also configure .to_ascii globally for any invocation:

ContentDisposition.to_ascii = ->(filename : String) { String.new(filename.encode("US-ASCII", invalid: :skip)) }

The .format method is aliased to .call, so you can do:

ContentDisposition.(disposition: "inline", filename: "råcëçâr.jpg")
# => "inline; filename=\"r%3Fc%3F%3F%3Fr.jpg\"; filename*=UTF-8''r%C3%A5c%C3%AB%C3%A7%C3%A2r.jpg"

There are also .attachment and .inline shorthands:

ContentDisposition.attachment("racecar.jpg")
# => "attachment; filename=\"racecar.jpg\"; filename*=UTF-8''racecar.jpg"
ContentDisposition.inline("racecar.jpg")
# => "inline; filename=\"racecar.jpg\"; filename*=UTF-8''racecar.jpg"

You can also create a ContentDisposition instance to build your own Content-Disposition header.

content_disposition = ContentDisposition.new(
  disposition: "attachment",
  filename:    "råcëçâr.jpg",
)

content_disposition.disposition
# => "attachment"
content_disposition.filename
# => "råcëçâr.jpg"

content_disposition.ascii_filename
# => "filename=\"r%3Fc%3F%3F%3Fr.jpg\""
content_disposition.utf8_filename
# => "filename*=UTF-8''r%C3%A5c%C3%AB%C3%A7%C3%A2r.jpg"

content_disposition.to_s
# => "attachment; filename=\"r%3Fc%3F%3F%3Fr.jpg\"; filename*=UTF-8''r%C3%A5c%C3%AB%C3%A7%C3%A2r.jpg"

Contributing

  1. Fork it (https://github.com/jetrockets/content_disposition/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors


*Note that all licence references and agreements mentioned in the ContentDisposition README section above are relevant to that project's source code only.