Yaws(erlang web服务器框架) 学习记录之文件上传

来源:互联网 发布:如何用telnet测试端口 编辑:程序博客网 时间:2024/06/06 02:43

Yaws提供了文件上传的API函数,从一些参考资料或Yaws的示例中,都提及使用yaws_api:parse_multipart_post/1这个API函数在服务器端进行文件数据的接受和处理。而在Yaws官方文档中,却提及了另一个API函数,即yaws_multipart:read_multipart_form/2在服务器端进行上传文件数据的处理。

由于,以前还没有接触过Yaws框架,所以详细阅读了相关资料。要掌握对文件上传的处理,除了掌握以上提到的API函数以外,还需要了解out/1函数在接受文件上传时的工作方法。

一、out/1函数在授受文件上传时的工作方法

1.对于较小的文件,浏览器会一次性将文件数据传送到服务器端,此时,out/1函数仅调用一次就完成了文件数据的接收;out/1函数返回相关的提示信息等即可。

2.对于较大的文件,浏览器会将上传的文件数据分块上传到服务器端,在服务器端进行接受时,要通过多次调用out/1函数来完成数据的接收和处理。此时,out/1函数需要多次返回{get_more,Content,State},表示还有下一块文件数据需要接收。这样,out/1函数会被反复调用,以接收文件数据并处理。直到out/1函数不返回get_more这个元组为止。而多次调用out/1函数时,相应的文件数据处理的状态({get_more,Content,State}中的State)会保存在arg记录中的state域中。

二、运用yaws_multipart:read_multipart_form/2函数解析文件数据,进行数据的保存或处理

yaws_multipart:read_multipart_form/2函数的参数有两个,第一个还是arg,而第二个是对接受文件数据处理的一些选项(用list来保存)。主要的选项有指示文件数据是存储在临时文件中还是存储在内存中,最后一并处理。其标志为no_temp_file这个原子值。

注意:如果文件保存在临时文件中,当临时文件用完后,应删除这个临时文件。

yaws_multipart:read_multipart_form/2函数返回的值有三种:

1.{get_more,Content,State} 与out/1相同,即此时表示文件数据的接收还没有完成,要处理好已接受的数据,并等待下次out/1函数的调用。

2.{done,Adict} 此时,上传的文件数据接收完成,可以对所有的数据时行处理。

3.{error,Reason} 即文件上传出错。

对于第2种情形很容易处理,即返回的Adict是一个dict。此时,调用dict:find/2来查找相应的参数(文件上传的文件域的名称),并处理返回的列表即可。具体的说,返回的列表主要包括:

[{filename, "name of the uploaded file as entered on the form"},
{value, Contents_of_the_file_all_in_memory} | _T]
or:
[{filename, "name of the uploaded file as entered on the form"},
{temp_file, "full pathname of the temp file"} | _T]

这两种形式的列表,第一种形式就是文件数据在内存中即 Contents_of_the_file_all_in_memory变量代表的值。第二种形式表示文件数据在临时文件中,其文件路径为字符串形式。

对于上传大文件的处理,可以使用如下形式的代码:

<erl>-record(upload, {          fd,          filename,          fixed_filename,          last = false,          param_name,          param_running_value,          params,          running_file_size = 0,          max_file_size,          no_temp_file,          temp_dir = yaws:tmpdir("/tmp"),          temp_file,          headers = [],          data_type = list}).    out(Arg) ->        % Options = [{temp_file,"my.txt"},{temp_dir,"./logs"}],        Options = [no_temp_file],        Parse =  yaws_multipart:read_multipart_form(Arg, Options),        case Parse of                                                            {done, _AllContents} when Arg#arg.state /= undefined -> %可以在此处进行文件数据接收完成后的处理,%此保护式用以区别上传小文件时一次的文件数据传送。                io:format("all:~p~n",[_AllContents]),                Upload = Arg#arg.state,                io:format("filename:~p~n",[Upload#upload.filename]),       %客户端上传的文件名称                io:format("tempname:~p~n",[Upload#upload.fixed_filename]), %服务器端临时文件路径                io:format("params:~p~n",[Upload#upload.params]),           %如果上传文件数据是在内存中的,则会放在Upload#upload.params中                {html,"once ok!"};                                         %返回上传文件成功的提示            {error, _Reason} -> {html,"error!"};            {get_more, Contents, State} ->                io:format("~n~p~n",[Contents]),                io:format("~n~p~n",[State]),                {get_more, Contents, State}                              %返回这个值时,表示会多次调用out/1函数来接收文件数据        end.</erl>

0 0
原创粉丝点击