i'm using NanoHTTPD webserver 2.1.0 on a Java Desktop Env. (no Android)
Everything is working fine...but not the file upload using the POST method (PUT is not supported with forms)
Here is my HTML code:
<form method="post" enctype="multipart/form-data">
choose a file<br>
<input name="file" type="file" size="50" maxlength="100000"">
<button type="submit">upload</button>
</form>
And here is my server methode:
public Response serve(IHTTPSession session) {
if (session.getMethod() == Method.POST) {
Map<String, String> files = new HashMap<String, String>();
session.parseBody(files);
//this prints {file=C:\path-to-java-tmp-files\NanoHTTPD-4635244586997909485}
//the number is always different
System.out.println(files.toString());
} else {
//page containing the index.html including the form
return page;
}
}
And here is the Problem: The temp-file doesn't exist. There is another temp-file with a different "number" at the end existing and this seems to be the correct file, because the content is the same as the content of the uploaded file. So how to get the correct temp-filename?
Another problem is: The temp-file contains the hole POST content:
-----------------------------115801144322347
Content-Disposition: form-data; name="file"; filename="filename.txt"
Content-Type: application/octet-stream
-->content of the uploaded file
-----------------------------115801144322347--
This is a problem if the content is a pic or a binary.
It seems NanoHTTPD doesn't do any spezial with a POST request. it does always the same...saving the request to a tmp-file and serving a page. So: - How to get the correct temp-file? --> I think this is a bug. I'm getting a correct path and name, but the "number" is broken. idk...should i temporarily change the java tmp-path if an upload happens and then delete the file always. Then I only have one tmp-file independent of any naming? - how to kill the html request header out of the file
Or i'm doing something wrong? Is this the correct way to upload files to nanohttpd?
thx for your help!
Old question! But I was looking for a solution to just this problem. I was having problems dealing with the IHTTPSession
input stream. Turns out the stream would prematurely run empty when reading it, and you have to go back for more. This occurred when I was sending application/octet-stream
data larger than around 500k (I didn't profile for an exact figure).
My solution is to open the IHTTPSession
input stream, and iteratively read the input stream until it is FULLY exhausted:
public Response post_upload(IHTTPSession session) {
System.out.println("received HTTP post with upload body...");
int streamLength = Integer.parseInt(session.getHeaders().get("content-length"));
System.out.println("Content length is: " + streamLength);
byte[] fileContent = new byte[streamLength];
try {
InputStream input = session.getInputStream();
int bytesRead = 0;
int iterations = 0;
while (bytesRead < streamLength) {
int thisRead = input.read(fileContent, bytesRead, streamLength-bytesRead);
bytesRead += thisRead;
iterations++;
}
System.out.println("Read " + bytesRead + " bytes in " + iterations + " iterations.");
}
catch (Exception e) {
System.out.println("We have other problems...");
}
return newFixedLengthResponse(Response.Status.OK, "application/json", "[\"no prob\"]");
}
I hope this helps.
I figured it out not long after I posted my "did you find a fix?" question, but forgot to post it until you replied today.
<form method="post" enctype="multipart/form-data" action="http://whatever.com/path/">
<input type="file" name="file" />
<input type="hidden" name="extra_data" value='blah blah blah' />
<input type="submit" value="Send" />
</form>
And the Java code:
if (session.getMethod() == Method.POST) {
try { session.parseBody(files); }
catch (IOException e1) { e1.printStackTrace(); }
catch (ResponseException e1) { e1.printStackTrace(); }
extraData = session.getParms().get("extra_data");
File file = new File(files.get("file"));
}
The important thing is that the data you're sending comes with file data, filename and file mime type.
In my case, I was using python request to POST and wasn't sending it sufficient data. The correct post structure would be:
file_data = { 'file': ('test.png', open('../some_file.png', 'rb'), 'image/png') }
requests.post("http://whatever.com/path", data = { 'extra_data': "blah blah blah" }, files = file_data)
The code above reads from "some_file.png", but tells the server it's called "test.png".
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With