With Apache/PHP5, is it possible to get the contents of an uploaded file directly without having it written to the file system?
Not much on Google about this, but it appears that files are always written to a temporary directory once they are uploaded.
Not sure i understand you, but i will try to answer.
http://www.w3schools.com/PHP/php_file_upload.asp
What you can learn here is that every file is uploaded to php's temp directory. Then it is up to your script to move/copy that file to some permanent web accessible directory, because file that was uploaded to php's temp dir is deleted after the script end executing.
On Linux you can create filesystem partitions in memory. If you can ensure that the uploaded file is written to the partition in memory, if will be stored in memory but act as if it were stored in the filesystem, making both Apache/PHP5 and you happy.
The problem is that any solution which writes files to memory rather than to the filesystem requires severe limitations on the size and quantity of the files. You will see a speed boost by avoiding writing to disk, but if you use enough memory to push other data into the pagefile or swap, your "optimization" will become counterproductive very quickly.
You can:
<?php
if (!empty($_FILES))
{
echo "<pre>";
print_r($_FILES);
echo file_get_contents($_FILES['file']['tmp_name']);
echo "</pre>";
}
?>
<form id="myForm" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="Send" />
</form>
Output:
Array
(
[file] => Array
(
[name] => mytextfile.txt
[type] => text/plain
[tmp_name] => D:\PHP\wamp\tmp\php1283.tmp
[error] => 0
[size] => 1473
)
)
My text file My text file My text file My text file My text file My text file
My text file My text file My text file My text file
My text file My text file My text file My text file My text file My text file
My text file My text file My text file
My text file My text file My text file My text file My text file
I don't know if it's restricted by some php.ini variable.
Related
I want to use a text-box, insert my file address is in the Desktop, and then upload it in the server, what should I do?
Is it because you dont like file uploader object how it looks?
If yes I suggest you to make it hidden but in background use its fuctionality.
Show file selected information in a textbox but keep the file into hidden file uploder object.
Another method to post files like audio and jpeg to server is to use Base64 format . Its consider as string but not recommanded for large files.
Then you need a backend function to save data into file object or simply insert data into database.
Do it this way:
$file_url= $_POST['file']; //Path of file to be uploaded
if file_exists($file_url):
$fh= fopen("NewfileName", a+);
fwrite($fh, file_get_contents($file_url));
fclose($fh);
endif;
I'm trying to build a simple image uploader using PHP. I do know how to code it, however I have a few concerns..
My question I had is the following: Is saving files which users send safe to save as the original file? With this I mean: Will I not get any vulnerabilities when I'm saving a file send by an user?
Let's say my PHP script does this: It retrieves the POST data, which includes a file send by a person on my website. Is it save to just move the file over to a directory, with original name, content, etcetera? Is there any harm in doing this, or should I rename these files to a random string?
If this isn't a safe way to do this, then what is? How would I verify the send content isn't harmful?
There are always vulnerabilities in storing and providing content provided by a client.
This blog post gives a good description of the vulnerabilities you could face, how they're exploited and how to protect against them. I suggest you use this as a reference: http://blog.insicdesigns.com/2009/01/secure-file-upload-in-php-web-applications/
Make sure you only process files with the correct ending. Image files are never executed by a webserver, but .php files are for example. So make sure the users don't upload any file that can be executed.
I'm not aware of file names that are harmful. For the content this is difficult to answer. I remember an attack vector with modified TIFF images on windows and one in libjpeg on *nix Systems. However you probably won't be able to find these things without completely decoding the image.
Here's another approach: use this (https://hacks.mozilla.org/2011/03/the-shortest-image-uploader-ever/) very short Image Uploader, by Paul Rouget, based on Imgur.com's API.
Instead of uploading directly to your database, let imgur do all the security and validation, then if you need to, link to or download the (safe) image via Imgur.
It's free for non-commercial and very cheap for commercial.
Basically, you can use imgur's API to safely upload images from your HTML page, with no server side code at all
Here's a live demo: (http://paulrouget.com/miniuploader/)
I would say 100% user upload file are NOT 100% SAFE
JPEG files can contain arbitrary data in them in addition to the actual image data; it's part of the spec. Thus, merely checking if an image is a valid JPEG does not mean that the file is necessarily completely harmless.
File upload without validation
HTML Form:
<form enctype="multipart/form-data" action="uploader.php" method="POST"> <input type="hidden" name="MAX_FILE_SIZE" value="100000" /> Choose a file to upload: <input name="uploadedfile" type="file" /><br /> <input type="submit" value="Upload File" /> </form>
PHP Code:
<?php
$target_path = "uploads/";
$target_path = $target_path . basename($_FILES['uploadedfile']['name']);
if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file " . basename($_FILES['uploadedfile']['name']) . " has been uploaded";
} else {
echo "There was an error uploading the file, please try again!";
}
?>
Define a .htaccess file that will only allow access to files with
allowed extensions.
Do not place the .htaccess file in the same directory where the
uploaded files will be stored. It should be placed in the parent
directory.
A typical .htaccess which allows only gif, jpg, jpeg and png files
should include the following (adapt it for your own need). This will
also prevent double extension attacks.
deny from all
<Files ~ “^w+.(gif|jpe?g|png)$”>
order deny,allow
allow from all
</Files>
If possible, upload the files in a directory outside the server root.
Prevent overwriting of existing files (to prevent the .htaccess
overwrite attack).
Create a list of accepted mime-types (map extensions from these mime types).
Generate a random file name and add the previously generated extension.
Don’t rely on client-side validation only, since it is not enough. Ideally one should have both server-side and client-side validation implemented.
I'm trying to upload some Excel files on the server, but unfortunately is doesn't work for some files.
my html code looks like this:
<form action="my_upload.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
php file looks like this
echo '<pre>';
print_r($_FILES);
echo '</pre>';
and the output
Array
(
[file] => Array
(
[name] => speeds.xls
[type] =>
[tmp_name] =>
[error] => 1
[size] => 0
)
)
It is not file path, naming, size or rights problem but it seems that is a file content problem. I'm saying that is a file content problem because the upload succeeds in some cases. Also if I re-save the Excel file that dind't work in the first place, then the upload file succeed.
How can I solve this problem? Why $_FILES['file']['error'] = 1. How to prevent that?
*Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini.*
The error code indicates that the file you're trying to upload is larger than the file upload size limit set in php.ini
You can get a full list of these codes here
You need to change the limit in php.ini to allow larger uploads. If you're on a hosted system you might need to check with them hoe to do this: arrangements vary from host to host.
Later or earlier in a web developers' life you'll have to deal with files and images uploaded by users.
Common questions:
How do I upload?
modern web browsers and techniques allow several ways to upload user-provided files to my server. What are best practises and what do I have to consider?
How do I process?
Once the upload is finished what do I need to know about security, and further processing of the files
How do I store and deliver?
Are there best practises on how to store the uploaded files?
disclaimer: I've put almost 30 minutes into the following answer, the initial question was removed so I decided to ask general questions a user may face when dealing with user-provided files. See my answer, you are free to contribute and add your ideas and experience
There is no "best" way for each of those steps, but a whole bunch of established ways and best practises among a variety of techniques and libraries which can help you to achieve user friendly uploads, security and speed.
For another question which was unfortunately deleted, I've written this small guide.
A user-contributed file or image walks through several stages in it's lifetime:
the upload itself
validaton
processing for storage (e.g. type conversion,resizing,thumbnail generation,...)
storing
delivery on the frontend side
This will adress all of the steps and provide examples as far as possible
1. The Upload
Modern web browsers offer several methods to upload a file.
The simplest way is to create a form with simple <input type="file" name="userFile" /> tag. Once the form is submitted, the file will be sent using POST and can be accessed with the $_FILES superglobal in PHP
1.1. Simple form in HTML
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="userFile1" />
<input type="file" name="userFile2" />
<input type="submit" value="upload files" />
</form>
When form is submitted, a POST request is sent to upload.php
This kind of upload isn't very userfriendly. Your user will not see any progress on the upload, and uploading several files will be a pain
1.2. Javascript ajax upload
In this solution, the POST is done asynchronously with javascript
http://www.saaraan.com/2012/05/ajax-image-upload-with-progressbar-with-jquery-and-php
1.3. HTML 5 Upload
modern browsers support HTML5, which allows very nice and userfriendly upload masks with progress bar and preview - border is your own creativity
For example, I really like this demo: http://html5demos.com/dnd-upload
On the server side
No matter which of those upload techniques you decide to use, the upload will end up in a HTTP POST sent to your script. All further processing will be done on the server.
PHP copies the file into a temporary path (upload_tmp_dir)
There are a few other upload-related settings you can tweak in your php.ini or on-the-fly with ini_set: http://php.net/manual/en/ini.core.php#ini.sect.file-uploads
upload.php
<pre>
<?php
print_r( $_FILES );
This is how the $_FILES superglobal looks like after a successful upload.
name: the original name
type: the browser-provided mime-type
size: the size in bytes
tmp_name: temporary filename on your server
error: error codes as described here, 0 when everything went file
Each file has it's own index
Array
(
[userFile1] => Array
(
[name] => i_love_ponies.png
[type] => image/png
[size] => 42233
[tmp_name] => /tmp/_x123tfsdayx134
[error] => 0
)
[userFile2] => Array
(
[name] => ponies_run_my_server.png
[type] => image/png
[size] => 12325
[tmp_name] => /tmp/_x3123asdad3ssy
[error] => 0
)
)
A few additional hints
If you are expecting large files, consider webserver and php execution timeouts. If an upload takes 10minutes you don't want your users to end up in an error.
In PHP you can increase the max_execution_time
2. Validation
Questions you might want to ask
Do I want to allow only specific files - what kind of file do I receive?
the type you find in the $_FILES array is set by the browser. If you want to be sure which type was uploaded you can use the fileinfo extension of PHP.
This example would check the success of the upload itself and write files of the allowed types into a fresh array for furter processing
$allowedTypes = array(
'image/png'
'image/gif'
'image/jpeg'
);
$useFiles = array();
$finfo = new finfo(FILEINFO_MIME_TYPE);
foreach ( $_FILES as $index => $file )
{
if ( $file['error'] === UPLOAD_ERR_OK ) {
$type = $finfo->file( $file['tmp_name'] );
if ( in_array( $type, $allowedTypes ) ) {
$useFiles[$index] = $file;
}
}
}
Do I want to set a maximum filesize - what is the size?
In this case you can safely rely on the $_FILES['key']['size'] value, which is the size in bytes. You should not just rely on the client-side set file size limitations
if talking about images, do I want to scale or create thumbnails - what are the image dimensions?
Have a look at getimagesize to determine image dimensions
3. Processing
Before saving the file to it's final location you might want to do some processing with it.
That's the time where you can
change image size for later displaying
create thumbnail
add watermark or branding
convert into another type. no link here because this can be any type, I am sure you find a solution to convert your .xxx to .yyy :)
Common libraries used for image processing are the gd lib and imagick. personally I prefer the gd lib. It is a bit more manual work, but it is faster and comes with most installations by default or is simple to install additionally. Imagemagick natively has a very huge pool of image processing functions
4. Storing your data
Now it is time to talk about storage. First a save way to copy your temporary file to a temporary or final location.
You should use move_uploaded_file
move_uploaded_file( $useFiles['tmp_name'], $destination );
Again, there's no "best way" for storing, this depends on your environment, files and use. I will talk about a few
4.1. server file system
This is probably the most used and simplest way to store your files. You can simply serve files statically with your already running webserver. This is usually a location within your document root.
To make your life easier, you can save the filename into a database - preferrably referencing or referenced by connected data like the user or a location.
You should not save all files into the same folder for various reasons.
You'd have to generate a unique name for each file, otherwise you overwrite an existing file with a new one. Also usual filesystems are getting slower to seek with increasing amounts of files in a node. This will result in slow response times when a file is requested for delivery.
You could save it into a folder for each user
/uploaded/user-id/file.jpg
If you expect a lot of files per user you could split a checksum of the filname to get a deeper folder structure
e.g.
$path = $_SERVER['DOCUMENT_ROOT'] . '/uploaded/' . $userId . '/' . chunk_split( md5( $useFiles['index']['name'] ), 12, '/' );
would result in
/var/www/htdocs/uploaded/1/97e262286853/d52aa8c58eb7/f0431f03/
4.2. Database
You could store your files into a MySQL database using the blob type. I don't recommend this generally
4.3. Content delivery network
If you expect a lot of traffic all over the globe, you might want to consider storing your files on a CDN like Amazon S3 with Cloudfront.
S3 is a cheap, reliable storage for files up to 5TB (as far as I know)
http://www.9lessons.info/2012/08/upload-files-to-amazon-s3-php.html
You will not have to worry about file backups, available harddisk size, delivery speed etc. etc. Cloudfront adds a CDN layer on top of S3 with edge locations all over the world
Right now I'm trying to write a script that will only accept certain audio files for upload to a server.
However, some MIME types are being returned as null.
Here is some code fragments:
PHP:
$allowedExt=array('audio/mp4a-latm');
if(isset($_POST))
{
print_r($_FILES);
//ToDo: Limit by File Size
if(in_array($_FILES["fileUpload"]["type"],$allowedExt)){
echo "file type found";
}
else
echo "wrong file type";
}
HTML:
<form action="php/FileUpload.php" method="POST" enctype="multipart/form-data">
Choose a file: <input name="fileUpload" type="file" /><br />
<input type="submit" value="Upload" />
</form>
The result of the above is:
Array ( [fileUpload] => Array ( [name] => 02 Helix Nebula.m4a [type] => [tmp_name] => <removed for space...>))
wrong file type
From what I understand, type should return the file's MIME type. In this case 'audio/mp4a-latm' for a .m4a file.
If php is properly returning null for .m4a files, then what would be the best approach to ensure I'm actually dealing with audio files? Is there anything more definite than just parsing for the file extensions? (ensure someone hasn't change the extension of say a text document)
The MIME element comes from the browser, which means it can be manipulated and thus is not trustworthy.
Either check the extension, or if you really want, parse the first few bytes of the file to make sure it's what is expected.
$_FILES['userfile']['type'] - The mime type of the file, if the browser provided this information.
http://www.php.net/manual/en/features.file-upload.post-method.php
That's why this method doesn't work well. You should compare file extension grabbed from
$_FILES['userfile']['name']
with acceptable extensions array (which you should create by yourself)
If you use php 5.3 or higher you can activate the php file info extension by escaping this line in your php.ini:
extension=php_fileinfo.dll
Then you can get your mime type from the file in php like this:
$pathToFile = 'my/path/to/file.ext';
$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($fileInfo, $pathToFile);
finfo_close($fileInfo);
This is more reliable than using what the browser sends you in the $_FILES array from your POST request.