Difference between file, file_get_contents, and fopen in PHP
The first two, file
and file_get_contents
are very similar. They both read an entire file, but file
reads the file into an array, while file_get_contents
reads it into a string. The array returned by file
will be separated by newline, but each element will still have the terminating newline attached, so you will still need to watch out for that.
The fopen
function does something entirely different—it opens a file descriptor, which functions as a stream to read or write the file. It is a much lower-level function, a simple wrapper around the C fopen
function, and simply calling fopen
won't do anything but open a stream.
Once you've open a handle to the file, you can use other functions like fread
and fwrite
to manipulate the data the handle refers to, and once you're done, you will need to close the stream by using fclose
. These give you much finer control over the file you are reading, and if you need raw binary data, you may need to use them, but usually you can stick with the higher-level functions.
So, to recap:
file
— Reads entire file contents into an array of lines.file_get_contents
— Reads entire file contents into a string.fopen
— Opens a file handle that can be manipulated with other library functions, but does no reading or writing itself.
PHP: What's the difference between fopen('file.txt', 'r') and file('file.txt')?
Here's some info. Quote on file()
, file_get_contents()
, and fopen()
:
The first two,
file
andfile_get_contents
are very
similar. They both read an entire file, butfile
reads the file into
an array, whilefile_get_contents
reads it into a string. The array
returned byfile
will be separated by newline, but each element will
still have the terminating newline attached, so you will still need to
watch out for that.The
fopen
function does something entirely different—it opens a
file descriptor, which functions as a stream to read or write the
file. It is a much lower-level function, a simple wrapper around the C
fopen
function, and simply callingfopen
won't do anything but
open a stream.Once you've open a handle to the file, you can use other functions
likefread
andfwrite
to manipulate the data the handle
refers to, and once you're done, you will need to close the stream by
usingfclose
. These give you much finer control over the file
you are reading, and if you need raw binary data, you may need to use
them, but usually you can stick with the higher-level functions.So, to recap:
file
— Reads entire file contents into an array of lines.file_get_contents
— Reads entire file contents into a string.fopen
— Opens a file handle that can be manipulated with other library functions, but does no reading or writing itself.
Credit goes to Alexis King.
byte position: file_get_contents vs fopen
You wrote
The data chunk is no valid image data
"image data" - but in your code you call fgets()
to read that data. That's wrong, as image is binary data, not a text file, so you don't want it read it by lines (docs):
fgets — Gets line from file pointer
This means fgets()
would stop reading from file once it finds what it considers line end marker, which usually means stopping earlier and reading less than $length
as there's pretty low chance such byte is not in the binary sequence.
So fgets()
wrong method to use and this is the main issue. Instead you should pick less smart fread()
(which does not know about lines and stuff, and just reads what you told). Finally you should fclose()
the handle when you done. And naturally you should always check for errors, starting from fopen()
:
if ($handle = fopen($binaryFile, 'rb')) {
if (fseek($handle, $offset) === 0) {
$imageData = fread($handle, $length);
if ($imageData === false) {
// error handling - failed to read the data
}
} else {
// error handling - seek failed
}
fclose($handle);
} else {
// error handling - can't open file
}
So always use right tool for the task, and if you are unsure what given method/function does, there's always not-that-bad documentation to peek.
faster fopen or file_get_contents?
fopen and file_get_contents are nearly equivalent
to speed up with consistence the page load you can use
http://www.php.net/fpassthru
or, even better
http://www.php.net/readfile
with those functions, content of file is printed directly, byte per byte
as opposed to file_get_contents, for example, where you store the whole data inside a variable
$var = file_get_contents();
so, to make these work correctly you will need to disable output buffering (otherwise it would make readfile() pointless) in the page that serves the images
hope this helps!
file_get_contents or fopen for reading several MB of php://input?
There is a shorter version still: copy
copy("php://input", $filename);
PHP already internally implements what your code does. (Not sure it would make a measurable difference). Albeit I'm uncertain why you'd create a temporary file first.
And if the input file is up to 500 MB, then the file_get_contents
approach wouldn't work anyway, as it had to keep all that data in a string / memory.
Are fread(), file() and file_get_contents() functions secure to the server when third-party external references are given as filename?
Most (maybe all) PHP file-based operations are done through streams, and each stream wrapper (file, http, ftp, etc.) has their own code and logic, which means each could also have potential security vulnerabilities.
The default stream wrappers and their corresponding handlers can be found in the source, and there's a great deep dive for implementors here, too.
You can manually register your own stream wrappers, too. In fact, you can also unregister existing wrappers, possibly core ones (I haven't tried), so you or someone else could inject vulnerable code in theory, too.
To the best of my knowledge, there are no publicly announced unpatched vulnerabilities related to these wrappers in the currently maintained versions of PHP. That's not to say that in the past there weren't, nor is it to say I know of any undisclosed ones.
To your second question, no, when a web browser visits a PHP page that uses file_get_contents
against an HTTP/HTTP stream, nothing from the browser's initial request (headers, etc.) will be added to the stream's request. That part is called the "stream context". The default values for an unspecified context can be manually inspected in the source for each wrapper. Look for code like context && (tmpzval = php_stream_context_get_option
and then find the corresponding else
.
Related Topics
In PHP How Does Usort() Function Works
Group Array Values Based on Key in PHP
Regex/Domdocument - Match and Replace Text Not in a Link
Multi-Byte Safe Wordwrap() Function for Utf-8
PHP Pdo Insert Batch Multiple Rows with Placeholders
Require_Once :Failed to Open Stream: No Such File or Directory
How to Make a Catch-All Route in Laravel
Send Emails with International Accent and Special Characters
Laravel - How to Get Current User in Appserviceprovider
How to Search Through a JSON Array in PHP
Get the Price of an Item on Steam Community Market with PHP and Regex
PHP Soap Client That Understands Multi-Part Messages
When and Why Should $_Request Be Used Instead of $_Get/$_Post/$_Cookie
Assets Not Referencing to Public Folder (Laravel)
How to Prefix a Positive Number with Plus Sign in PHP
Woocommerce - How to Create Multiple Single Product Template Based on Category