views:

48

answers:

1

When uploading one file using <input type="file" /> in Opera, it works as expected. That is, you find the expected file data in $_FILES in PHP server side.

However, when I try to upload several files at once using Opera, by setting <input type="file" min="1" max="999" /> then all the files' contents are glued together in one long string and sent as POST data. All the files in this string are separated by headers such as this:

------------94QV8HRqBwta8NY4L2WH0r
Content-Disposition: form-data; name="file[]"; filename="xxx1069225496.xml"
Content-Type: text/xml

<?xml>
...

Opera follows the Webforms 2.0 standard, I know. But is there a simple way to make Opera send multiple files in the same fashion other browsers do, or will I have to write an interpreter to get files just from Opera?

Thanks for any help. Below is the HTML I'm currently using.


<div id="filearea">
    <input type="file" min="1" max="6000" accept="text/xml" name="file[]" style="padding: 1px; margin: 2px 0px;" />
</div>

This is how the var_dump of $_POST looks (I've erased any actual XML data, taking up space)

array(1) {
  ["file"]=>
  array(1) {
    [0]=>
    string(4209) "------------94QV8HRqBwta8NY4L2WH0r
Content-Disposition: form-data; name="file[]"; filename="1219854274.xml"
Content-Type: text/xml

<?xml version="1.0"?>
...

------------94QV8HRqBwta8NY4L2WH0r
Content-Disposition: form-data; name="file[]"; filename="xxx1069225496.xml"
Content-Type: text/xml

<?xml version="1.0"?>
...

------------94QV8HRqBwta8NY4L2WH0r
Content-Disposition: form-data; name="file[]"; filename="xxx1111008062.xml"
Content-Type: text/xml

<?xml version="1.0"?>
...

------------94QV8HRqBwta8NY4L2WH0r
Content-Disposition: form-data; name="file[]"; filename="1219854274.xml"
Content-Type: text/xml

<?xml version="1.0"?>
...
    "
  }
}
+1  A: 

I just checked a PHP bug report, and it claimed that this works in Opera:

<input type="file" name="file" min="1" max="999" />

But that this does not:

<input type="file" name="file[]" min="1" max="999" />

Edit: After testing this, I believe the PHP person who marked the bug as bogus didn't know what he was talking about... I cannot get either way to work natively with PHP.

As far as I can tell, PHP does not support Opera's 'mixed' file uploads. This is not a bug on Opera's part, as they are implementing it per the RFC's specification. I believe the other browsers simply upload the files as if there were multiple input elements. You could easily add support for this by checking the _POST array:

   $file = $_POST['file'][0];

   while (preg_match('/^(-+[A-Za-z0-9]+)\s+/', $file, $matches))
   {
      $id = $matches[1];

      $i = strlen($matches[0]);
      $body = false;
      $headers = array();
      while (($j = strpos($file, "\n", $i)) !== false)
      {
         $line = substr($file, $i, $j - $i);
         $i = $j + 1;
         if (trim($line) == '')
         {
            $body = true;
            break;
         }

         list($key, $val) = explode(':', trim($line), 2);
         $headers[$key] = trim($val);
      }
      if (!$body) break;

      $j = strpos($file, $id, $i);

      $data = substr($file, $i, $j-$i);
      echo $data."<HR>"; // also check $headers

      $file = substr($file, $j);
   }

There may be some off-by one errors in the above code.

konforce
I don't understand what you mean. `type="file"` is already my code. In case you meant `name` and not `type` is tried that, but it made no difference other than changing the POST string headers to this: `Content-Disposition: form-data; name="file"; filename="1220713927.xml"Content-Type: text/xml`
Codemonkey
Sorry, I meant to put [] on the name. As far as I can tell, PHP does not support this properly. You could split on the boundaries by hand, but it would probably be easier to simply create multiple INPUT elements.
konforce
How can it be PHP that does not support this properly when this error only occurs using Opera? It would be easier for me to create multiple INPUT elements, true. But sadly it would not be easier for the user that wants to upload 50 XML documents. I am still open for more suggestions!
Codemonkey
Which browsers, other than Opera, even support this functionality? Anyway, you may want to consider something like http://www.plupload.com, because you are correct, forcing the user to select that many different documents is not a valid solution.
konforce
All other major browsers support this (except Internet Explorer) but via HTML5 and now WebForms 2.0. It does strike me as odd that Opera would choose to sabotage their own multi file upload like this, so I assumed there would be a form- or input property I could set to get the standard behavior.
Codemonkey
The other browsers support the `multiple` attribute, which you've not included in your code, which is why I asked. Anyway, I've updated my answer with some code to decode Opera's multi-upload. The other browsers should work fine via the regular $_FILES array.
konforce