0

I have a device that submits ~20,000 small 16-byte binary files (data from RFID tags) as multipart/form-data to a URL of my choice.

------WebKitFormBoundaryP1dTbAtca8AXmaAM
Content-Disposition: form-data; name="400000001"; filename="400000001.bin"
Content-Type: application/vnd.ply-badge

⚉⟗⢑☭⥢↺⡠⥔
------WebKitFormBoundaryP1dTbAtca8AXmaAM
Content-Disposition: form-data; name="400000002"; filename="400000002.bin"
Content-Type: application/vnd.ply-badge

⨧ⶈⰡⰑ⸈ⱬ⋪⣫

I want to insert this data into a SQL database. Right now the back end for the rest of this application is PHP, so I would like to do this in PHP as well. Right now I am getting

PHP Warning: Maximum number of allowable file uploads has been exceeded in Unknown on line 0

I'm aware I can raise the limit in the php.ini file, and if I do it works, but it writes all 20,000 files to disk. Since this is less than 400K of actual data (maybe a few MB once you include metadata) I would like to just load it into memory and skip the filesystem all together. Does PHP have an option to load values like this into $_POST rather than writing them to disk and using $_FILES? If not, is there some other mechanism that will let me parse this data without writing everything to disk?

Unfortunately this is on a Windows server, so in-memory filesystems are... complicated.

9072997
  • 849
  • 7
  • 21
  • There would be no point loading anything into the $_POST array. You could but why not just load the files into your own array. Remember, $_POST does not survive the end of the running script – RiggsFolly Jun 30 '22 at 14:59
  • Can you change how it's uploaded? It seems like JSON would be a better way to do it. – Barmar Jun 30 '22 at 14:59
  • Also, PHP only save these uploaded files as temp files, I assume that is what you mean by loading files to disk. If you want those to survive past the end of the scripts execution you have to save them somewhere else yourself. I think I am basically saying I am not sure what you are trying to do here! – RiggsFolly Jun 30 '22 at 15:02
  • @RiggsFolly loading things into my own array would be fine. I just assumed since PHP will load things into $_POST if they don't have a filename that there might be an option to make it do this in spite of the filename. My own code will persist them to SQL. – 9072997 Jun 30 '22 at 15:07
  • @Barmar unfortunately, no. It's a vendor provided device. – 9072997 Jun 30 '22 at 15:08
  • Once you are delivered $_POST by PHP you can do what you like with it, but if you are asking if instead of using $_FILES you can make files get uploaded in the $_POST I dont think so – RiggsFolly Jun 30 '22 at 15:12
  • @RiggsFolly that is indeed what I am asking – 9072997 Jun 30 '22 at 15:13

1 Answers1

1

I guess this could work, if you do two things:

a) prevent PHP from automatically parsing this request, and

b) parsing the request body yourself afterwards.

PHP automatically parses the request because of the Content-Type: multipart/form-data request header - so that would have to be manipulated, before the request reaches PHP.
With Apache as the web server, this can be done using the RequestHeader directive. (With IIS or nginx, you'd have to figure out what equivalent they offer.)

Would make most sense to set it to just text/plain, I think. That should prevent PHP from doing any parsing on its own, so $_POST and $_FILES won't be populated either.

Now you can read the request body via php://input, and parse it yourself. Some hints on the latter can be found under Manually parse raw multipart/form-data data with PHP, there's also libraries out there on GitHub etc.

Of course at this point you'd have to make sure that you choose a parser implementation, that does not create temporary files again, but provides you access to the data in form of an array or object.

CBroe
  • 91,630
  • 14
  • 92
  • 150
  • 1
    This was 90% of what I needed. The last 10% is that you can prevent PHP from automatically parsing the request via [enable_post_data_reading](https://www.php.net/manual/en/ini.core.php#ini.enable-post-data-reading) which can be set in [.user.ini](https://www.php.net/manual/en/configuration.file.per-user.php) – 9072997 Jul 04 '22 at 20:31
  • @9072997 now I learned something new, because I was not aware that option explicitly existed. That is a bit easier than what I suggested :-) – CBroe Jul 05 '22 at 05:54