allow to set filename for send_file

if the disposition type matches "attachment", this
indicates that the recipient should prompt the user to save the response
locally, rather than process it normally
This commit is contained in:
Anton Maminov 2018-12-23 13:24:27 +02:00
parent a5d8df7382
commit 6f111ffbb0
2 changed files with 52 additions and 17 deletions

View File

@ -1,4 +1,5 @@
require "./spec_helper"
require "./handler_spec"
describe "Macros" do
describe "#public_folder" do
@ -114,6 +115,17 @@ describe "Macros" do
response.headers["Content-Type"].should eq("application/octet-stream")
response.headers["Content-Length"].should eq("6")
end
it "sends file with given path and given filename" do
get "/" do |env|
send_file env, "./spec/asset/hello.ecr", filename: "image.jpg"
end
request = HTTP::Request.new("GET", "/")
response = call_request_on_app(request)
response.status_code.should eq(200)
response.headers["Content-Disposition"].should eq("attachment; filename=\"image.jpg\"")
end
end
describe "#gzip" do

View File

@ -109,7 +109,13 @@ end
# ```
# send_file env, "./path/to/file", "image/jpeg"
# ```
def send_file(env : HTTP::Server::Context, path : String, mime_type : String? = nil)
#
# Also you can set the filename and the disposition
#
# ```
# send_file env, "./path/to/file", filename: "image.jpg", disposition: "attachment"
# ```
def send_file(env : HTTP::Server::Context, path : String, mime_type : String? = nil, *, filename : String? = nil, disposition : String? = nil)
config = Kemal.config.serve_static
file_path = File.expand_path(path, Dir.current)
mime_type ||= Kemal::Utils.mime_type(file_path)
@ -120,6 +126,7 @@ def send_file(env : HTTP::Server::Context, path : String, mime_type : String? =
request_headers = env.request.headers
filesize = File.size(file_path)
filestat = File.info(file_path)
attachment(env, filename, disposition)
Kemal.config.static_headers.try(&.call(env.response, file_path, filestat))
@ -147,6 +154,31 @@ def send_file(env : HTTP::Server::Context, path : String, mime_type : String? =
return
end
# Send a file with given data and default `application/octet-stream` mime_type.
#
# ```
# send_file env, data_slice
# ```
#
# Optionally you can override the mime_type
#
# ```
# send_file env, data_slice, "image/jpeg"
# ```
#
# Also you can set the filename and the disposition
#
# ```
# send_file env, data_slice, filename: "image.jpg", disposition: "attachment"
# ```
def send_file(env : HTTP::Server::Context, data : Slice(UInt8), mime_type : String? = nil, *, filename : String? = nil, disposition : String? = nil)
mime_type ||= "application/octet-stream"
env.response.content_type = mime_type
env.response.content_length = data.bytesize
attachment(env, filename, disposition)
env.response.write data
end
private def multipart(file, env : HTTP::Server::Context)
# See http://httpwg.org/specs/rfc7233.html
fileb = file.size
@ -188,22 +220,13 @@ private def multipart(file, env : HTTP::Server::Context)
end
end
# Send a file with given data and default `application/octet-stream` mime_type.
#
# ```
# send_file env, data_slice
# ```
#
# Optionally you can override the mime_type
#
# ```
# send_file env, data_slice, "image/jpeg"
# ```
def send_file(env : HTTP::Server::Context, data : Slice(UInt8), mime_type : String? = nil)
mime_type ||= "application/octet-stream"
env.response.content_type = mime_type
env.response.content_length = data.bytesize
env.response.write data
# Set the Content-Disposition to "attachment" with the specified filename,
# instructing the user agents to prompt to save.
private def attachment(env : HTTP::Server::Context, filename : String? = nil, disposition : String? = nil)
disposition = "attachment" if disposition.nil? && filename
if disposition && filename
env.response.headers["Content-Disposition"] = "#{disposition}; filename=\"#{File.basename(filename)}\""
end
end
# Configures an `HTTP::Server::Response` to compress the response