在cowboy2中使用静态文件处理程序提供文件时,是否可以进行"下载" filename与磁盘上的实际文件名不同?
例如,我们假设我正在提供静态文件" 123"。当用户在浏览器中下载它时,是否可以将其作为" 123.txt"?
因为现在,我的所有文件名都会自动分配一个带有" .dms"的文件名。扩展
答案 0 :(得分:1)
我认为静态处理程序的正常操作不是返回浏览器下载的文件。
当静态处理程序无法[识别]扩展名时,它会 将文件作为application / octet-stream发送。接收这样的浏览器 文件将尝试将其直接下载到磁盘。
备份一点,http响应几乎总是包含一个Content-Type
标头,它指定发送到浏览器的内容类型,以便浏览器知道如何显示内容。内容的类型使用mime type
指定。包含典型html页面的响应具有如下所示的Content-Type标头:
Content-Type: text/html; charset=utf-8
text/html
mime类型告诉浏览器不要将文件显示为文本,而是将文本显示为html。
Cowboy查看请求的文件的扩展名,以确定在响应中的Content-Type标头中指定的mime类型。如果文件没有扩展名,则Cowboy将mime类型指定为application/octet-stream
,这会导致浏览器下载该文件。你的浏览器基本上说,“我不知道如何显示这个二进制数据,所以在这里,你拿出文件并弄清楚如何处理它。”
如果所有没有扩展名的文件都是(普通)文本文件,那么你可以告诉牛仔为匹配路由的所有文件设置mime类型text/plain
:
hello_erlang / SRC / hello_erlang_app.erl:
-module(hello_erlang_app).
-behaviour(application).
-export([start/2]).
-export([stop/1]).
start(_Type, _Args) ->
Dispatch = cowboy_router:compile([
{'_', [
{"/dog/[...]", cowboy_static,
{
priv_dir,
hello_erlang,
"static/assets",
[{mimetypes, {<<"text">>, <<"plain">>, []} }] %<**HERE
}
},
{"/please_upgrade_to_websocket", myws_handler, []}
]}
]),
{ok, _} = cowboy:start_clear(my_http_listener,
[{port, 8080}],
#{env => #{dispatch => Dispatch} }
),
hello_erlang_sup:start_link().
stop(_State) ->
ok.
Mime类型使用语法word1/word2
,牛仔采用您在此处指定的内容:
[{mimetypes, {<<"text">>, <<"plain">>, []} }]
并用正斜杠加入这两个单词,为mime类型生成“text / plain”。
目录结构:
hello_erlang/priv/static/assets/
file1
file2
file3
URL:
http://localhost:8080/dog/file1
您还可以告诉牛仔调用自定义函数来设置文件的mime类型:
hello_erlang / SRC / hello_erlang_app.erl:
-module(hello_erlang_app).
-behaviour(application).
-export([start/2]).
-export([stop/1]).
start(_Type, _Args) ->
Dispatch = cowboy_router:compile([
{'_', [
{"/dog/[...]", cowboy_static,
{
priv_dir,
hello_erlang,
"static/assets",
[{mimetypes, my_mime_setter, set_type}] %<** HERE {mimetypes, MODULE, FUNCTION}
}
},
{"/please_upgrade_to_websocket", myws_handler, []}
]}
]),
{ok, _} = cowboy:start_clear(my_http_listener,
[{port, 8080}],
#{env => #{dispatch => Dispatch} }
),
hello_erlang_sup:start_link().
stop(_State) ->
ok.
hello_erlang / SRC / my_mime_setter.erl:
-module(my_mime_setter).
-export([set_type/1]).
set_type(Path) ->
Fname = filename:basename(Path),
TextFiles = [<<"file1">>, <<"file2">>],
case filename:extension(Fname) of
<<>> -> %no extension found(Yeah, I thought this would be an empty list, too!)
case lists:member(Fname, TextFiles) of
true -> {<<"text">>, <<"plain">>, []};
false -> {<<"text">>, <<"html">>, []}
end;
Ext ->
case Ext of
<<".html">> -> {<<"text">>, <<"html">>, []};
<<".css">> -> {<<"text">>, <<"css">>, []};
<<".js">> -> {<<"application">>, <<"javascript">>, []};
_Other -> {<<"application">>, <<"octet-stream">>, []}
end
end.
您可以使用以下文件测试自定义mime setter:
hello_erlang / PRIV /静态/资产/ file1的:
<div><font color="red">red text</font></div>
hello_erlang / PRIV /静态/资产/ file4将:
<div><font color="red">red text</font></div>
如果您要求提供第一个文件:
http://localhost:8080/dog/file1
mime类型将设置为text/plain
,浏览器不会呈现html,而是会看到原始html。如果您请求第二个文件:
http://localhost:8080/dog/file4
mime类型将设置为text/html
,这将导致浏览器呈现文本,您应该看到一些红色文本。
如果你想对有扩展名的文件进行试探,可以写下:
_Ext ->
cow_mimetypes:web(Fname)
牛仔会用它的算法来制作一个mime类型。