PostgreSql Large Object to file through PHP PDO - php

This code outputs LO to browser:
...
$my_pdo_connect->beginTransaction();
$stream = $my_pdo_connect->pgsqlLOBOpen($oid, 'r');
fpassthru($stream);
...
But I stuck with writing LO to file system.
I am aware about pg_lo_export and lo_export, but there is
restriction to use PHP PDO capabilities only.
Obviously I should use some php-function instead of fpassthru($stream) to write the stream into a file, can't find suitable docs or example.

Finally I found how to solve the issue:
$my_pdo_connect->beginTransaction();
$stream = $my_pdo_connect->pgsqlLOBOpen($oid, 'r');
$file = fopen('my_file', 'w');
stream_copy_to_stream($stream, $file);
fclose($file);

Related

Why fread (PHP) don't read entire file?

I have this code on PHP that load a local file:
$filename = "fille.txt";
$fp = fopen($filename, "rb");
$content = fread($fp, 25699);
fclose($fp);
print_r($content);
With this code I can see all the contents of the file. But when I change the $filename to a external link, like:
$filename = "https:/.../texts/fille.txt";
I can't see all the contents of the file, he appears cut to me. Whats the problem?
The fread() function can be used for network operations. But network connections work different than file system operations. A network cannot read a bigger file in a single attempt, that is not how typical networks work. Instead they work package based. So data arrives in chunks.
And if you take a look into the documentation of the function you use then you will see that:
Reading stops as soon as one of the following conditions is met:
[...]
a packet becomes available or the socket timeout occurs (for network streams)
[...]
So what you observe actually is documented behavior. You need to continue to read packages in a loop to get the whole file. Until you received an EOF.
Take a look yourself: https://www.php.net/manual/en/function.fread.php
And further down in that documentation you will see that example:
Example #3 Remote fread() examples
<?php
$handle = fopen("http://www.example.com/", "rb");
if (FALSE === $handle) {
exit("Failed to open stream to URL");
}
$contents = '';
while (!feof($handle)) {
$contents .= fread($handle, 8192);
}
fclose($handle);
?>

fgetcsv returning NULL in PHP 4

One of our systems is running on PHP 4 and no I can't change that.
The fgetcsv function seems to return null no matter what file I upload.
Very simply put:
$handle = fopen($file,"r");
var_dump(fgetcsv($handle));
fclose($handle);
This will print out "NULL".
Doing var_dump on the $handle object does give me a resource:
resource(33) of type (stream)
But I just get NULL when using fgetcsv
I can get the contents of the file using file_get_contents, but then it's more awkawrd to parse it as a csv.
As I say, I can't really do anything about it being on PHP 4. Does anyone know what might be causing this, or shall I find another way?
Thanks
Your original issue may be related to temporary uploaded file usage.
Try to open it after move_uploaded_file
Also, fseek($handle, 0) can help theoretically, because it was read already anywhere.
I can get the contents of the file using file_get_contents
You can try to use tmpfile then:
$csv = file_get_contents($file);
$temp = tmpfile();
fwrite($temp, $csv);
fseek($temp, 0); // prepare for read at start
$data = fgetcsv($temp);
fclose($temp); // file autoremoved here

Alternative way to read raw I/O stream in PHP

I am trying to find an alternative to reading php://input. I use this for getting XML data from a CURL PUT.
I usually do this with:
$xml = file_get_contents('php://input');
However, I'm having a few issues with file_get_contents() on Windows.
Is there an alternative, perhaps using fopen() or fread()?
Yes, you can do:
$f = fopen('php://input', 'r');
if (!$f) die("Couldn't open input stream\n");
$data = '';
while ($buffer = fread($f, 8192)) $data .= $buffer;
fclose($f);
But, the question you have to ask yourself is why isn't file_get_contents working on windows? Because if it's not working, I doubt fopen would work for the same stream...
Ok. I think I've found a solution.
$f = #fopen("php://input", "r");
$file_data_str = stream_get_contents($f);
fclose($f);
Plus, with this, I'm not mandated to put in a file size.

Using a php://memory wrapper causes errors

I'm trying to extend the PHP mailer class from Worx by adding a method which allows me to add attachments using string data rather than path to the file.
I came up with something like this:
public function addAttachmentString($string, $name='', $encoding = 'base64', $type = 'application/octet-stream')
{
$path = 'php://memory/' . md5(microtime());
$file = fopen($path, 'w');
fwrite($file, $string);
fclose($file);
$this->AddAttachment($path, $name, $encoding, $type);
}
However, all I get is a PHP warning:
PHP Warning: fopen() [<a href='function.fopen'>function.fopen</a>]: Invalid php:// URL specified
There aren't any decent examples with the original documentation, but I've found a couple around the internet (including one here on SO), and my usage appears correct according to them.
Has anyone had any success with using this?
My alternative is to create a temporary file and clean up - but that will mean having to write to disc, and this function will be used as part of a large batch process and I want to avoid slow disc operations (old server) where possible. This is only a short file but has different information for each person the script emails.
It's just php://memory. For example,
<?php
$path = 'php://memory';
$h = fopen($path, "rw+");
fwrite($h, "bugabuga");
fseek($h, 0);
echo stream_get_contents($h);
yields "bugabuga".
Quickly looking at http://php.net/manual/en/wrappers.php.php and the source code, I don't see support for the "/' . md5(microtime());" bit.
Sample Code:
<?php
print "Trying with md5\n";
$path = 'php://memory/' . md5(microtime());
$file = fopen($path, 'w');
if ($file)
{
fwrite($file, "blah");
fclose($file);
}
print "done - with md5\n";
print "Trying without md5\n";
$path = 'php://memory';
$file = fopen($path, 'w');
if ($file)
{
fwrite($file, "blah");
fclose($file);
}
print "done - no md5\n";
Output:
buzzbee ~$ php test.php
Trying with md5
Warning: fopen(): Invalid php:// URL specified in test.php on line 4
Warning: fopen(php://memory/d2a0eef34dff2b8cc40bca14a761a8eb): failed to open stream: operation failed in test.php on line 4
done - with md5
Trying without md5
done - no md5
The problem here simply is the type and the syntax:
php://memory and php://temp are read-write streams that allow temporary data to be stored in a file-like wrapper. The only difference between the two is that php://memory will always store its data in memory, whereas php://temp will use a temporary file once the amount of data stored hits a predefined limit (the default is 2 MB). The location of this temporary file is determined in the same way as the sys_get_temp_dir() function.
In short, the type you want is temp instead and the syntax you want is:
php://temp/maxmemory:$limit
The $limit is in bytes. You want to count that using safe byte functions.

Best way to download a file in PHP

Which would be the best way to download a file from another domain in PHP?
i.e. A zip file.
The easiest one is file_get_contents(), a more advanced way would be with cURL for example. You can store the data to your harddrive with file_put_contents().
normally, the fopen functions work for remote files too, so you could do the following to circumvent the memory limit (but it's slower than file_get_contents)
<?php
$remote = fopen("http://www.example.com/file.zip", "rb");
$local = fopen("local_name_of_file.zip", 'w');
while (!feof($remote)) {
$content = fread($remote, 8192);
fwrite($local, $content);
}
fclose($local);
fclose($remote);
?>
copied from here: http://www.php.net/fread
You may use one code line to do this:
copy(URL, destination);
This function returns TRUE on success and FALSE on failure.

Categories