Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

126 lines (92 sloc) 2.925 kB
<html>
<h2> File upload </h2>
<p>This page shows how to upload a file to the webserver, nothing of course
actually gets written to disk, but the upload code is
<a href="code.yaws?file=/upload.yaws">here in file upload.yaws</a>
</p>
<erl>
-record(upload, {
fd,
filename,
last}).
-define(DIR, "/tmp/YawsTestUploads/").
out(A) when A#arg.state == undefined ->
State = #upload{},
multipart(A, State);
out(A) ->
multipart(A, A#arg.state).
err() ->
{ehtml,
{p, [], "error"}}.
multipart(A, State) ->
Parse = yaws_api:parse_multipart_post(A),
case Parse of
{cont, Cont, Res} ->
case addFileChunk(A, Res, State) of
{done, Result} ->
Result;
{cont, NewState} ->
{get_more, Cont, NewState}
end;
{result, Res} ->
case addFileChunk(A, Res, State#upload{last=true}) of
{done, Result} ->
Result;
{cont, _} ->
err()
end;
{error, _Reason} ->
err()
end.
addFileChunk(A, [{part_body, Data}|Res], State) ->
addFileChunk(A, [{body, Data}|Res], State);
addFileChunk(_A, [], State) when State#upload.last==true,
State#upload.filename /= undefined,
State#upload.fd /= undefined ->
file:close(State#upload.fd),
%%file:delete([?DIR,State#upload.filename]),
Res = {ehtml,
{p,[], "File upload done"}},
{done, Res};
addFileChunk(A, [], State) when State#upload.last==true ->
{done, err()};
addFileChunk(_A, [], State) ->
{cont, State};
addFileChunk(A, [{head, {_Name, Opts}}|Res], State ) ->
case lists:keysearch("filename", 1, Opts) of
{value, {_, Fname0}} ->
Fname = yaws_api:sanitize_file_name(basename(Fname0)),
%% we must not put the file in the
%% docroot, it may execute uploade code if the
%% file is a .yaws file !!!!!
file:make_dir(?DIR),
case file:open([?DIR, Fname] ,[write]) of
{ok, Fd} ->
S2 = State#upload{filename = Fname,
fd = Fd},
addFileChunk(A, Res, S2);
Err ->
{done, err()}
end;
false ->
addFileChunk(A,Res,State)
end;
addFileChunk(A, [{body, Data}|Res], State)
when State#upload.filename /= undefined ->
case file:write(State#upload.fd, Data) of
ok ->
addFileChunk(A, Res, State);
Err ->
{done, err()}
end.
basename(FilePath) ->
case string:rchr(FilePath, $\\) of
0 ->
%% probably not a DOS name
filename:basename(FilePath);
N ->
%% probably a DOS name, remove everything after last \
basename(string:substr(FilePath, N+1))
end.
</erl>
</html>
Jump to Line
Something went wrong with that request. Please try again.