argv0 / webmachine_examples

No description has been added.

commit 0: eeac8c49a47d
branch: default
tags: tip
HTML file upload example for Webmachine
an...@thedude.desk.cbc.basho.com
8 months ago
webmachine_examples / fileupload / src / fileupload_resource.erl
r0:eeac8c49a47d 42 loc 1.9 KB embed / history / annotate / raw /
-module(fileupload_resource).
-export([init/1, to_html/2, allowed_methods/2, process_post/2]).
-define(STORE_PATH, "/tmp/fileupload_demo").
-include_lib("webmachine/include/webmachine.hrl").

init([]) -> {ok, no_state}.

allowed_methods(ReqData, C) -> {['GET', 'POST'], ReqData, C}.

process_post(ReqData, C) ->
    ContentType = wrq:get_req_header("content-type", ReqData),
    Boundary = string:substr(ContentType, string:str(ContentType, "boundary=") 
                             + length("boundary=")),
    {FileName, FileSize, Content} = get_streamed_body(
                                      webmachine_multipart:stream_parts(
                                        wrq:stream_req_body(ReqData, 1024), 
                                        Boundary), [],[]),
    StorePath = filename:join([?STORE_PATH,"/", FileName]),
    filelib:ensure_dir(StorePath),
    file:write_file(StorePath, Content),
    NewRD = wrq:append_to_response_body(
              io_lib:format(
                "<html><head><title>Upload Complete</title></head>"
                "<body><h1>Upload Complete</h1>"
                "<p>Received file ~s (~.2fK)</p></body></html>",
                [filename:basename(StorePath), FileSize]), ReqData),
    {true, NewRD, C}.

to_html(ReqData, C) ->
    {"<html><head><title>Webmachine File Upload Example</title></head>"
     "<body><h1>Webmachine File Upload Example</h1>"
     "<form action='/' method='POST' enctype='multipart/form-data'>"
     "Upload File:&nbsp<input type='file' name='filedata'/>"
     "<input type='submit' value='Upload'></form></body></html>", 
     ReqData, C}.

get_streamed_body(done_parts, FileName, Acc) ->
    Bin = iolist_to_binary(lists:reverse(Acc)),
    {FileName, size(Bin)/1024.0, Bin};
get_streamed_body({{"filedata", {Params, _Hdrs}, Content}, Next}, Props, Acc) ->
    FileName = binary_to_list(proplists:get_value(<<"filename">>, Params)),
    get_streamed_body(Next(),[FileName|Props],[Content|Acc]).