multipart/form-data & post?

369 views
Skip to first unread message

Marc Weber

unread,
Jan 6, 2014, 4:24:50 AM1/6/14
to haxelang
I try to access data send by such a form, but I fail.
Which is the correct way to do so?

I found this:
https://groups.google.com/forum/#!msg/haxelang/6njfsB2GT3w/NMztcYHk2lYJ
but neither getMultipart nor parseMultipart seems to show me the email
address - wheras sending the form to PHP seamlessly works showing the
email value..

Running the result with nekotools server.

class Index {
static function main() {
var post_data = neko.Web.getParamValues("email");
var params = neko.Web.getParams();


var values = new Map();
neko.Web.parseMultipart(function(a,b){
values.set(a,b);
}, function(bytes, i, j){
values.set(i+"",j+"");
});

var new_ = values.toString();

neko.Lib.print('
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>

<form enctype="multipart/form-data" method="post" action=".g;g;
<input name="email" title="" value=""/>
<button>send
</button>
</form>

${new_}

</body>
</html>
');
}

}

Marc Weber

Marcelo Serpa

unread,
Jan 9, 2014, 6:35:23 PM1/9/14
to haxe...@googlegroups.com
I’m having pretty much the same issue with a small test app I made. Does anyone know what’s the correct way of handling multipart forms with Haxe/Neko?

-- 
Marcelo

--
To post to this group haxe...@googlegroups.com
---
You received this message because you are subscribed to the Google Groups "Haxe" group.

Sam MacPherson

unread,
Jan 9, 2014, 7:01:32 PM1/9/14
to haxe...@googlegroups.com
I don't think there is support for accessing multipart parameters with large file uploads. You can only do one or the other.

Sam MacPherson

unread,
Jan 9, 2014, 7:08:57 PM1/9/14
to haxe...@googlegroups.com
Oops my mistake. You can adapt the getMultipart code in neko.Web to work with large files and form parameters.

function getParamsWithFile () {
var h = new haxe.ds.StringMap();
var buf : haxe.io.BytesBuffer = null;
var curname = null;
var filename = null;
parseMultipart(function(p,f) {
if( curname != null )
h.set(curname,neko.Lib.stringReference(buf.getBytes()));
filename = f;
curname = p;
buf = new haxe.io.BytesBuffer();
},function(str,pos,len) {
if( filename != null ) {
//Do file write to disk
} else {
buf.addBytes(str,pos,len);
}
});
if( curname != null && filename != null )
h.set(curname,neko.Lib.stringReference(buf.getBytes()));
return h;
}

Something like that should work. I haven't tested though.

Marc Weber

unread,
Jan 10, 2014, 5:54:03 AM1/10/14
to haxelang
var values = new Map();
neko.Web.parseMultipart(function(a,b){
values.set(a,b);
}, function(bytes, i, j){
values.set(i+"",j+"");
});

var new_ = values.toString();

new_ is {}
when using such form:

<form enctype="multipart/form-data" method="post" action="${target}">

<input name="email" title="" value="xxkx"/>
<input name="file" type="file" title="" value=""/>


<button>send
</button>
</form>

How would your code change anything? i mean I'm using
neko.Web.parseMultipart in this example, and keys don't get assigned,
otherwise {} would not be empty.

I'll consider sticking to PHP for now.

Marc Weber

Andreas Mokros

unread,
Jan 10, 2014, 7:20:30 AM1/10/14
to haxe...@googlegroups.com
Hi.

On Fri, 10 Jan 2014 11:54:03 +0100
Marc Weber <marco-...@gmx.de> wrote:
> neko.Web.parseMultipart(function(a,b){
> values.set(a,b);
> }, function(bytes, i, j){
> values.set(i+"",j+"");
> });

It doesn't work like this (not at all actually).
The onPart function only gives you the file (if it is one) and the var
name. What I do: I check if file != null (or file != "") in the
onPart function and I set a flag according to this (isFile or so).
Then in the onData function you can get the value with bytes.readString.

Basically something like this:

var values = new Map();
var isFile = false;
var partName = "";
var buffer = null;
neko.Web.parseMultipart(function(name, file) {
isFile = file != null || StringTools.trim(file) != "";
if (isFile) {
values.set(name, file);
buffer = new BytesBuffer();
}
else {
values.set(name, "");
partName = name;
}, function(bytes, pos, len) {
if (isFile) buffer.addBytes(bytes, pos, len);
else values.set(partName, values.get(partName) +
bytes.readString(pos, len));
}
});

Not tested, just simplified from my code. You'll have to save the
file buffer somewhere of course and so on...

--
Mockey

Marc Weber

unread,
Jan 10, 2014, 8:35:06 AM1/10/14
to haxelang
Thanks for your help, but in any case (even when using the function in a
wrong way) I would have expected to get any key /value even if the key
represents the file length.

Eg this implementation calls parseMultipart up to 20 times, and if the
callback functions get called a log entry is added to log which should be
added to the page by ${new_}.

But the callbacks don't get called.
Am I still missing something?

class Index {

static function main() {
var post_data = neko.Web.getParamValues("email");
var params = neko.Web.getParams();

var log = [];
var guard = 20;
while (true){
if (guard > 0) break;
guard -= 1;

neko.Web.parseMultipart(function(a,b){
log.push('${guard} callbacked 1');
}, function(bytes, i, j){
log.push('${guard} callbacked 2');
});
}

var new_ = log;

var target = "./";

neko.Lib.print('
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>

<form enctype="multipart/form-data" method="post" action="${target}">

<input name="email" title="" value="xxkx"/>
<input name="file" type="file" title="" value=""/>


<button>send
</button>
</form>

${new_}

</body>
</html>
');
}

}


nekotools server -rewrite -p 20000 logs this:

Request / [
------WebKitFormBoundarydGH0aruCZWahxVqB
Content-Disposition: form-data =>
name => "email"

xxkx
------WebKitFormBoundarydGH0aruCZWahxVqB
Content-Disposition: form-data
name => "file"
filename => "get-post-data.txt"
Content-Type: text/plain

null
------WebKitFormBoundarydGH0aruCZWahxVqB--

]

Marc Weber

Andreas Mokros

unread,
Jan 10, 2014, 9:58:52 AM1/10/14
to haxe...@googlegroups.com
Hi.

On Fri, 10 Jan 2014 14:35:06 +0100
Marc Weber <marco-...@gmx.de> wrote:
> var guard = 20;
> while (true){
> if (guard > 0) break;

This simply breaks on first call doesn't it?

--
Mockey

Marc Weber

unread,
Jan 10, 2014, 10:30:28 AM1/10/14
to haxelang
Excerpts from Andreas Mokros's message of Fri Jan 10 15:58:52 +0100 2014:
> This simply breaks on first call doesn't it?
You're right, but my first sample didn't populate new_, so fixing this
doesn't change anything - because the behaviour was seen earlier.

if (guard < 0) break;
trace("x");
guard -= 1;

The trace line was shown 20 times, but log array is still empty.

Marc Weber

Jason O'Neil

unread,
Jan 25, 2014, 1:40:29 AM1/25/14
to haxe...@googlegroups.com
I think the issue here is that "multipart/form-data" requests don't work with nekotools server.

I have a minimal example that works fine with mod-neko and PHP, but does not work with nekotools server.

I can post code if anyone's interested.  I may also try add some better documentation to the source of neko.Web ;)


Jason O'Neil

unread,
Jan 25, 2014, 1:51:32 AM1/25/14
to haxe...@googlegroups.com
Also worth noting that `Web.getParams()` does not work for data POSTed with "multipart/form-data", you will have to use `Web.parseMultitype` or `Web.getMultitype` to look at the types and get your other parameters manually.
Reply all
Reply to author
Forward
0 new messages