检测image类型及尺寸的erlang模块

Socklabs在其项目中需要限制用户上传的图片类型为gif,png和jpeg, 同时图片文件大小必须 < 4M, 图片尺寸小于2048*2048.这个模块很简单,以binary的方式读取文件,随后通过图片相应的格式解析,获取格式,尺寸相关信息.随后可以做出判断.
代码 下载:

-module(ipwfiles_image).
-export([image_type/1]).

-compile([export_all]).

image_type(File) when is_list(File) ->
case file:read_file(File) of
{ok, Data} ->
image_type(Data);
_ ->
{error, openfile}
end;

%% Gif header, width and height
%% http://www.etsimo.uniovi.es/gifanim/gif87a.txt
image_type(<<$G, $I, $F, $8, $9, $a, Width:16/little, Height:16/little, _/binary>>) ->
{gif, Width, Height};
image_type(<<$G, $I, $F, $8, $7, $a, Width:16/little, Height:16/little, _/binary>>) ->
[...]

Erlang的模块参数声明

浏览Mochiweb的源代码的时候,发现了一个比较陌生的module attribute声明。
在erlang的maillist中找到了答案!网上有两篇文章对其进行了描述,这里简单概述一下,具体可以参看原文:
http://www.clickcaster.com/items/the-black-art-of-erlangs-parameterized-modules
http://www.lshift.net/blog/2008/05/18/late-binding-with-erlang
在模块的attribute声明中,我们可以采用这样的形式:

-module(fruit, [Param1, Param2]).
-export([show/0]).
show() ->
io:format(”fruit:~p~p~n”, [Param1, Param2]).

这里声明了Module fruit,同时指明了传递给fruit的参数:Param1,Param2。erlang的编译器会自动的export一个Name:new的函数,因此我们可以这样使用此Module:
Module = fruit:new(”Apple”, “Banana”),
Module:show().
也可以使用这种方式进行调用:
{fruit, “Apple”, “Banana”}:show().
这个特性有点类似OOP语言中,对象的创建。在erlang中,其实完全可以通过record作为参数传递,来实现同样的功能。因此在某些erlang ”纯粹者“严重,这样的新特性值得怀疑。

erlang twitter client and module attributes

国外一个朋友写的erlang client
http://github.com/boost/erlang_twitter/tree/master
这个client是命令行形式的,README中包含简单的用法。
主要是一个erl源文件实现了一个gen_server behaviour,用来登录以及获取各种timeline,以及发送信息。
代码很简短,使用了inets相关的module进行通讯,同时使用xml相关的module解析xml。
有兴趣的朋友可以看看代码。
好多天不写blog,惭愧啊。
今天说一下module的Attributes,Attribute形式如下:
-Attr(Value).
其中Attr为atom,Value可以为任何直接的term。
Attribute包含预定义的Attributes以及用户自定义的Attributes。
预定义模块Attribute(Pre-Defined Module Attributes):
-module(Module)
名为Module的模块声明,Module为atom,Module必须与此文件文件名相同(除去.erl后缀名,比如module1.erl,则Module为module1)
-export(Functions)
说明本模块导出的函数列表,Functions形式如下[Function1/Artiy1, ..., FunctionN/ArityN],其中FunctionN为atom,ArtityN为integer
-import(Module, Functions)
引入某个模块的函数列表,这样使用Module的函数时,可以像使用本地函数一样,不用指定模块前缀。Functions与export中的Functions相同,Module为atom。推荐不要使用import,因为容易混淆,而且影响代码自动更新。(这里类似C++中的using namespace std; 这样以后使用stl相关的函数,类时不用添加std::前缀)
-compile(Options)
指定编译选项,具体参考compile文档。在我们写代码时,经常使用-compile(export_all),将本模块中的所有函数导出,这里仅是为了测试代码方便,在最后的产品中,应该尽力减少每个模块导出的函数。
-vsn(Vsn)
模块的版本信息,Vsn为一个字面信息,可以为任何Term。可以通过beam_lib:version/1获取,如果没有指定vsn则默认为Module的checksum
注意:-record,-macro不时模块的属性,尽管它们很像。
用户自定义Attributes(User-Defined Attributes):
-SomeTag(Value)
SomeTag为atom,Value为任何具有直接字面意义的Term。
Attribute的获取
Module的Attributes信息,会在Module被编译的时候添加到beam文件中。因此可以通过Module:module_info()获取Moudle的整体信息,也可以通过Module:module_info(attributes)获取所有用户自定义的属性信息。也可以通过:beam_lib:chunks(”module.beam”, [attributes])获取所有用户自定义的属性信息。
让我们写一小段代码,用来方便获取某个属性:

-module(extract).
-export([attribute/2]).
attribute(File, Key) ->
case beam_lib:chunks(File, [attributes]) of
{ok, {_Module, [{attributes, L}]}} ->
case lookup(Key, Key) of
[...]