使用静态处理程序时是否可以更改下载文件名?

时间:2018-02-23 21:29:26

标签: erlang cowboy

在cowboy2中使用静态文件处理程序提供文件时,是否可以进行"下载" filename与磁盘上的实际文件名不同?

例如,我们假设我正在提供静态文件" 123"。当用户在浏览器中下载它时,是否可以将其作为" 123.txt"?

因为现在,我的所有文件名都会自动分配一个带有" .dms"的文件名。扩展

1 个答案:

答案 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类型。