Erlang 从URL中截取尾部文件名

分析项目edownloader时看到的代码:

从 “http://www.aaaa.com.cn/download/bbb/ccc.exe”  中截取ccc.exe

uri.hrl

  1. -record(uri, {scheme,       %% ”http”, ”ftp”
  2.               user_info=”", %% [] | ”srp”
  3.               host=”",      %% ”somewhere.net”
  4.               port=”",      %% [] | 80 | 8080
  5.               path=”",      %% ”/here/there/everytwhere”
  6.               raw_query=”", %% ”id=12345&name=fred+johnson”. undecoded.
  7.               frag=”",      %% ”some anchor”
  8.               raw           %% original raw uri
  9.              }).

uri.erl

  1. from_string(Uri) ->
  2.     %{http,ELS}
  3.     {Scheme, Uri1} = parse_scheme(Uri),
  4.     %{www.xxx.com:port,ELS}
  5.     {Authority, Uri2} = parse_authority(Uri1),
  6.     %{[],”www.xxx.com:port”}
  7.     {UserInfo, HostPort} = parse_user_info(Authority),
  8.     %{www.xxx.com,port}
  9.     {Host, Port} = parse_host_port(HostPort),
  10.     %
  11.     {Path, Uri3} = parse_path(Uri2),
  12.     {Query, Uri4} = parse_query(Uri3),
  13.     Frag = parse_frag(Uri4),
  14.     new(Scheme, UserInfo, Host, Port, Path, Query, Frag, Uri).
  15. %http
  16. parse_scheme(Uri) ->
  17.     parse_scheme(Uri, []).
  18. parse_scheme([$: | Uri], Acc) ->
  19.     {lists:reverse(Acc), Uri};
  20. parse_scheme([], Acc) ->
  21.     {[], lists:reverse(Acc)};
  22. parse_scheme([C | Rest], Acc) ->
  23.     parse_scheme(Rest, [C | Acc]).
  24. parse_authority(“//” ++ Uri) ->
  25.     parse_authority(Uri, ”");
  26. parse_authority(Uri) ->
  27.     Uri.
  28. %www.xxx.com
  29. parse_authority([$/ | Rest], Acc) ->
  30.     {lists:reverse(Acc), [$/ | Rest]};
  31. parse_authority([], Acc) ->
  32.     {lists:reverse(Acc), []};
  33. parse_authority([C | Rest], Acc) ->
  34.     parse_authority(Rest, [C | Acc]).
  35. parse_user_info(Authority) ->
  36.     parse_user_info(Authority, []).
  37. parse_user_info([$@ | HostPort], Acc) ->
  38.     {lists:reverse(Acc), HostPort};
  39. parse_user_info([], Acc) ->
  40.     {[], lists:reverse(Acc)};
  41. parse_user_info([C | HostPort], Acc) ->
  42.     parse_user_info(HostPort, [C | Acc]).
  43. parse_host_port(HostPort) ->
  44.     case string:tokens(HostPort, ”:”) of
  45.         [Host] -> {Host, ”"};
  46.         [Host, Port] -> {Host, list_to_integer(Port)};
  47.         _ -> throw({uri_error, {invalid_host_port, HostPort}})
  48.     end.
  49. parse_path(Uri) ->
  50.     parse_path(Uri, []).
  51. parse_path([C | Uri], Acc) when C == $?; C == $# ->
  52.     {lists:reverse(Acc), [C | Uri]};
  53. parse_path([], Acc) ->
  54.     {lists:reverse(Acc), ”"};
  55. parse_path([C | Uri], Acc) ->
  56.     parse_path(Uri, [C | Acc]).
  57. parse_query([$? | Uri]) ->
  58.     parse_query(Uri, []);
  59. parse_query(Uri) ->
  60.     {“”, Uri}.
  61. parse_query([$# | Uri], Acc) ->
  62.     {lists:reverse(Acc), [$# | Uri]};
  63. parse_query([], Acc) ->
  64.     {lists:reverse(Acc), ”"};
  65. parse_query([C | Rest], Acc) ->
  66.     parse_query(Rest, [C | Acc]).
  67. parse_frag([$# | Frag]) ->
  68.     unquote(Frag);
  69. parse_frag(“”) ->
  70.     ”";
  71. parse_frag(Data) ->
  72.     throw({uri_error, {data_left_after_parsing, Data}}).
  73. new(Scheme, UserInfo, Host, Port, Path, Query, Frag, Uri) ->
  74.     update_raw(#uri{scheme = Scheme,
  75.                     user_info = unquote(UserInfo),
  76.                     host = Host,
  77.                     port = Port,
  78.                     path = unquote(Path),
  79.                     raw_query = Query,
  80.                     frag = unquote(Frag),
  81.                     raw = Uri}).
  82. new(Scheme, UserInfo, Host, Port, Path, Query, Frag) ->
  83.     update_raw(#uri{scheme = Scheme,
  84.                     user_info = unquote(UserInfo),
  85.                     host = Host,
  86.                     port = Port,
  87.                     path = unquote(Path),
  88.                     raw_query = Query,
  89.                     frag = unquote(Frag)}).
  90. update_raw(Uri) ->
  91.     Uri#uri{raw = iolist_to_string(to_iolist(Uri))}.
  92. iolist_to_string(Str) ->
  93.     binary_to_list(iolist_to_binary(Str)).
  94. unquote(Str) ->
  95.     unquote(Str, []).
  96. unquote([], Acc) ->
  97.     lists:reverse(Acc);
  98. unquote([$+ | Str], Acc) ->
  99.     unquote(Str, [$  | Acc]);
  100. unquote([$\%, A, B | Str], Acc) ->
  101.     unquote(Str, [erlang:list_to_integer([A, B], 16) | Acc]);
  102. unquote([C | Str], Acc) ->
  103.     unquote(Str, [C | Acc]).

 

edownload_util.erl

  1. filename_from_uri(Uri) when is_list(Uri) ->
  2.     filename_from_uri(uri:from_string(Uri));
  3. filename_from_uri(Uri) when is_record(Uri, uri) ->
  4.     Path = Uri#uri.path
  5.     %, {match, Start, Len} = regexp:match(Path, ”([^/]+){1}quot;)
  6.     , {match, [{Start, Len},_]} = re:run(Path, ”([^/]+){1}quot;)
  7.     , string:substr(Path, Start+1, Len)
  8. .

3> edownload_util:filename_from_uri(“http://www.baidu.com/download/emessager.apk”).
结果:”emessager.apk”



发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(Spamcheck Enabled)