1

I have the contents of a file in a string. I need to pass this file to a function where the function is expecting the parameter to be the name of the file, not the contents. The obvious and probably simplest way to do this would be to write the contents to a temp file, then pass that file name to the function, and unlink the file once I'm finished.

However, I'm looking for a solution that doesn't involve writing the file out to the file system and then reading it back in. I've had a need for this in multiple cases, so I'm not looking for a work-around to a specific function, but more of a generic method that will work for any function expecting a file name (like file_get_contents(), for instance).

Here are some thoughts, but not sure how to pursue these yet:

  • Is it possible to write the contents somewhere in memory, and then pass that to the function as a filename? Perhaps something using php://memory.
  • Is it possible to write the contents to a pipe, then pass the name of the pipe to the function?

I did a short proof-of-concept trying with php://memory as follows, but no luck:

$data = "This is some file data.\n";
file_put_contents( 'php://memory', $data );
echo file_get_contents( 'php://memory' );

Would be interested in knowing of good ways to address this. Googling hasn't come up with anything for me.

Nick Coons
  • 3,682
  • 1
  • 19
  • 21
  • You have avoided the elephant in the room. What function are you using? – Andreas Dec 23 '18 at 07:27
  • From https://stackoverflow.com/questions/7719376/what-happens-when-php-temp-is-opened-more-than-once it seems that if you open php://memory twice then it will be different content anyway. – Nigel Ren Dec 23 '18 at 07:38
  • You might be able to use [mikey179/vfsStream](https://github.com/mikey179/vfsStream) but this sounds a bit of an XY problem. I mean, if you know that the string's contents came from a file, why not just use that file? – Alex Howansky Dec 23 '18 at 07:39
  • @Andreas I'm not avoiding that, I addressed it by saying that I'm looking for a generic solution that will work with any function expecting a file name. In this particular instance, I'm working with `curl_file_create()`, but I'm not sure that's relevant. – Nick Coons Dec 23 '18 at 07:54
  • @AlexHowansky "if you know that the string's contents came from a file" - In this particular case, the contents of the file are being received into an API, so there is no file on disk to which I have access, only the contents as a string. I'd like to pass this data to a function expecting a file name without having to first write it out to disk (seems like a waste of resources). – Nick Coons Dec 23 '18 at 07:56
  • @NigelRen Okay, so it might be that I can't use something like `php://memory`. – Nick Coons Dec 23 '18 at 07:58
  • Perhaps try [`tmpfile()`](http://php.net/manual/en/function.tmpfile.php), which whilst writing to the fs, it may be a memory based fs (I use tmpfs). if you read the User Contributed Notes it tells you how to get the actual file name. – Nigel Ren Dec 23 '18 at 08:03
  • Another thing to consider is how much IO is being performed, there are usually several layers of caching going on before your file hits any physical media, so if the file is small and very transient it may not make any real difference. – Nigel Ren Dec 23 '18 at 08:07
  • @NigelRen That's what I was planning to do if I can't find a more elegant solution. I'm not concerned with I/O load, just more interested in a clean solution that didn't unnecessarily write out a temp file because a function can't take file data. – Nick Coons Dec 23 '18 at 08:09

3 Answers3

4

It mainly depends on what the target function does with the file name. If you're lucky, you can register your own stream wrapper:

stream_wrapper_register('demo', 'DemoStream');

$data = "This is some file data.\n";
$filename = 'demo://foo';
file_put_contents($filename, $data);
echo file_get_contents($filename);
Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • 1
    This looks promising. For reference, here is the documentation on what an example class looks like: http://php.net/manual/en/stream.streamwrapper.example-1.php – Nick Coons Dec 23 '18 at 15:05
  • 1
    I just put together a proof-of-concept using the example, and implementing a basic `stream_stat()` function (required by `file_get_contents()`) and it works great, thank you! – Nick Coons Dec 23 '18 at 15:16
0

Why not use a file in the /tmp/ directory? Like this:

<?php

$filename = '/tmp/mytmpfile';
$data = "This is some file.\n";
file_put_contents($filename, $data);
$result = file_get_contents($filename);
var_dump($result);
EvE
  • 734
  • 3
  • 13
0

Well, as you say you don't want to use a file, you shouldn't use file_get_contents(). But you can achieve the same result by using stream_get_contents(), like this:

<?php
$data = "This is some file data.\n";
$handle = fopen('php://memory', 'r+'); // open an r/w handle to memory
fputs($handle, $data); // write the data
rewind($handle); // rewind the pointer
echo stream_get_contents($handle); // retrieve the contents
EvE
  • 734
  • 3
  • 13
  • In using this method, what value could I pass to a function (like `file_get_contents()`) that requires a file name? – Nick Coons Dec 23 '18 at 15:00