This is a comment that is too long to post as a comment. I have marked it community wiki for this reason. Whether I am right or not in my conclusion, it is probably appropriate to reportWhether I am right or not in my conclusion, it is probably appropriate to report this to WRI as a bug to know for sure. Christopher's answer pretty much confirms that this to WRI asis a bug to know for surein Mathematica, that can only be worked around with an undocumented hack.
Here is a simple PHP script that I created to compare the request generated by a form and the request generated by Mathematica:
<html>
<h1>Form</h1>
<form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data">
<p><input type="file" name="jpgFile"></p>
<p><input type="submit"></p>
</form>
<h1>Files</h1>
<pre>
<?php
print_r($_FILES);
?>
</pre>
<h1>Request data</h1>
<pre>
<?php
print_r($_REQUEST);
?>
</pre>
<h1>Request meta information</h1>
<pre>
<?php
print_r($_SERVER);
?>
</pre>
</html>
Mathematica code:
SystemOpen@Export["~/Desktop/test.html", URLFetch[
"http://localhost:8080/upload.php",
"Method" -> "POST",
"MultipartElements" -> {
{"image", "image/jpeg"} -> ExportString[jpgFile, "JPEG"]
}], "Text"]
The content type of the request is multipart/form-data as it should be, but instead of sending the file as a file, it sends it as a parameter. That is, it shows up in $_REQUEST instead of $_FILES; this will never work regardless of what you do on your end.
The only options I believe are to either build your own procedure that uses Java (or another external tool) like you did, or use a workaround that sends the image as a string. But for those kinds of workarounds you need to have access to the backend so that you can decode the string on the server. For example I recently wrote a Mathematica code that uploaded images by first encoding them as base64 strings and then sending them as string parameters:
ExportString[Import["~/Desktop/example.png", "String"], "Base64"];