2020年9月25日金曜日

Sinatra で attachment を使ってブラウザにファイルのダウンロードをさせる方法

概要

Sinatra でクライアント側にコンテンツをファイルとしてをダウンロードさせるには attachment が便利です
使い方と attachment の仕組みを紹介します

環境

  • macOS 10.15.6
  • Ruby 2.7.1p83
    • sinatra 2.0.7

準備

  • bundle init
  • vim Gemfile
gem "sinatra"
  • bundle install

テキストファイルをダウンロードさせる

attachment を使います
content_type を使ってちゃんとファイルの形式を指定してあげるとクライアントにもやさしいので指定しましょう
以下の場合だと「ok」と記載された data.txt がダウンロードできます

require 'sinatra/base'

class App < Sinatra::Base
  get '/download' do
    content_type "text/plain"
    attachment "data.txt"
    "ok"
  end
end

Content-Disposition ヘッダにファイル名が記載されている

実は attachment は Content-Disposition を操作しているだけのようです (参考)
クライアント側、例えばブラウザや curl, wget などに対して「このパスへのアクセスはファイルに保存してね」というのを教えて上げているだけになります

  • Content-Disposition: attachment; filename="data.txt"

なのでクライアント側はちゃんとヘッダを参照していない場合は単純に「ok」を表示するだけになります

ブラウザで動作確認

Chrome などのブラウザは当然ヘッダを見るようになっているのでファイルとしてダウンロードできます
localhost:9292/download にアクセスするとちゃんと data.txt がダウンロードできるのが確認できると思います

curl で動作確認

curl でも Content-Disposition を見てファイルに保存することができます
-J でヘッダを参照し -O でファイルに保存することができます
もしヘッダに記載のファイル名で保存したい場合は -J-O を一緒に指定しましょう

  • curl -J -O localhost:9292/download

HEAD だけ確認したい

事前にどんなファイル名になるのか確認したい場合があると思います
そんな場合は HEAD メソッドを使って一度ヘッダの情報のみ参照しましょう
curl の場合は -I オプションを使います (-XHEAD ではないのでご注意 (参考))

  • curl -I localhost:9292/download
HTTP/1.1 200 OK
Content-Type: text/plain;charset=utf-8
Content-Disposition: attachment; filename="data.txt"
Content-Length: 2
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin

0 件のコメント:

コメントを投稿