PHP: File upload with Unicode - php

When I try to loop through the $_FILES array in PHP I get an error, because the filenames are all in unicode. Is it somehow possible to still accept files with unicode filenames?
Example code:
foreach ($_FILES["files"]["error"] as $key => $error)
{
$tmp_name = $_FILES["files"]["tmp_name"][$key];
$name = $_FILES["files"]["name"][$key];
logz( "$tmp_name AND $path/$name" );
if ( $error == UPLOAD_ERR_OK )
{
move_uploaded_file($tmp_name, "$path/$name");
logz( "$tmp_name -> $path/$name" );
}
else
{
logz( "upload error" );
}
}
Pay attention to the log parameter; the output is:
/ -> path/%7B
The filename is not complete and $_FILES['files']['name'] is empty.

Related

Php saves uploaded files with wrong encoding on linux server

I have a classic php script for saving tmp files:
$uploads_dir = "scans";
var_dump( $_FILES );
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
rename($tmp_name, urldecode("/var/www/html/$uploads_dir/$name") );
}
}
echo urldecode("/var/www/html/$uploads_dir/$name");
However, the file 'фавикон.png' gets saved as 'фавикон.png'. Please help me out what to do with encoding.
Thank you
EDIT:
Got it working with iconv function. However, for some weird reason it had to be encoded into windows format.
The resulting code:
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
$name =iconv('UTF-8','windows-1251', $name);
copy($tmp_name, "/var/www/html/$uploads_dir/$name");
}
You might need the following setlocale(LC_ALL, 'ru_RU.utf8')
try to put this line on the top of the script:
header('Content-Type: text/html; charset=utf-8');
Have you try to use utf8_decode:
utf8_decode($name);
I suggest that you change the name of the file, there are very good reasons to do this. Check this post for more details: https://stackoverflow.com/a/17866898/1016425

Renaming filenames and immediately reading files having issues in php

I have pdf files which are report cards of students.The report card names format is <student full name(which can have spaces)><space><studentID>.I need to download files.For this I have used the following code.
if(file_exists($folder_path.'/') && is_dir(folder_path)) {
$report_files = glob(folder_path.'/*'.'_*\.pdf' );
if(count($report_files)>0)
{
$result_data = '';
$result_data = rename_filenamespaces($report_files);
var_dump($result_data);//this shows the edited filename
foreach ($result_data as $file) {
if (strpos($file,$_GET['StudentID']) !== false) {
//code for showing the pdf docs to download
}
}
}
}
//function for renaming if filename has spaces
function rename_filenamespaces($location)
{
$new_location = $location;
foreach ($location as $file) {
//check file has spaces and filename has studentID
if((strpos($file," ")!==false)&& (strpos($file,$_GET['StudentID']) !== false))
{
$new_filename = str_replace(" ","-",$file);
rename($file,$new_filename);
$new_location = $new_filename;
}
}
return $new_location;
}
The variable $result_data gives me the filename without spaces,but the for each loop is showing Warning:Invalid argument supplied for foreach(). But the filename is changed in the server directory immediately after running the function. This warning shows only for first time. I am unable to solve this.
$new_location = $new_filename;
$new_location is a array
$new_filename is a string
You have to use $new_location[$index]
or try
foreach ($new_location as &$file) {
...
...
$file = $new_filename;

Issues with Uploading Multiple files with PHP

I can see this question has been asked a million times before. I have been through many of the responses and can't seem to get it right:-
I am simply trying to upload multiple files. I'm certain that the form is correct. The issue I get is that if I use a foreach loop, PHP cycles through 5 times (I guess once for each key in $_FILES).
I have read that you should count the uploaded files in the $_FILE['file_upload'] array, then use a for loop, and include an index on the end, such as:-
$_FILES['file_upload']['name'][$1]
however, when I try to access those values I only get the first letter of the value (I think I understand why this is).
The only thing I can think is to use
for($i ; $i<$size ; $i++){...}
and then nest a foreach loop inside it, however, this seems inefficient and I've seen no other suggestions to this end.
I would therefore be eternally grateful if someone could set me straight once and for all. My code is here:-
foreach ($_FILES['file_upload'] as $key => $value){
$tmp_file = $_FILES['file_upload']['tmp_name'];
$target_file = basename($_FILES['file_upload']['name']);
if(move_uploaded_file($tmp_file,$upload_location."/".$target_file)){
$message = "File uploaded successfully";
} else {
$error = $_FILES['file_upload']['error']; // get the error
$_SESSION['errors'][] = $error_msg[$error];// return the error that matches
}// end if
} // end for
So just to clarify - The above code works and uploads the image, but where the loop cycles through 5 times (I'm assuming once per $_FILES attribute), I am getting 5 error messages.I hope this makes sense.
Many thanks in advance for any pointers
Phill
The following was taken from: PHP Manual
<?php
$uploads_dir = '/uploads';
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
}
?>
Which in turn you should be able to modify to something like this:
<?php
$uploads_dir = '/uploads';
foreach ($_FILES["file_upload"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["file_upload"]["tmp_name"][$key];
$name = $_FILES["file_upload"]["name"][$key];
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
}
?>
change your foreach to this
foreach ($_FILES['file_upload']['tmp_name'] as $key => $value){
$tmp_file = $_FILES['file_upload']['tmp_name'][$key];
$target_file = basename($_FILES['file_upload']['name'][$key]);
if(move_uploaded_file($tmp_file,$upload_location."/".$target_file)){
$message = "File uploaded successfully";
} else {
$error = $_FILES['file_upload']['error'][$key]; // get the error
$_SESSION['errors'][] = $error_msg[$error];// return the error that matches
}// end if
} // end for
I dont think I understand you completely. If you are uploading multiple files, you should use foreach (no counter required).
The only counter you should use is to count the numbers of files that were successfuly uploaded.
Try this:
$success = 0;
foreach ($_FILES['files']['name'] as $file => $name){
$tmp_file = $_FILES["files"]["tmp_name"][$file];
$target_file = $name;
if(move_uploaded_file($tmp_file,$upload_location."/".$target_file)){
$message = "File uploaded successfully";
$success++;
} else {
$error = $_FILES['file_upload']['error']; // get the error
$_SESSION['errors'][] = $error_msg[$error];// return the error that matches
}// end if
} // end for
echo $success.' files were uploaded';

can't upload multiple images iin zend freamework on server

i have a problem with upload mutilply files using zend framework on server
actually my code works correctly on localhost but on remote server it gives me application error message
my host is ipage.com
$upload = new Zend_File_Transfer_Adapter_Http();
$upload->setDestination('projects\\'.$_pId);
// $_pid is my project folder where all files related to it uploded
$files = $upload->getFileInfo();
$i = 1;$g = 1;
foreach ($files as $file => $info)
{
// i have three kinds of images
// innerfinishingphotos_ images which can be more than 1 file eg :innerfinishingphotos_1, innerfinishingphotos_2, innerfinishingphotos_3.
// outerfinishingphotos_ images which can be more than 1 file eg :outerfinishingphotos_1, outerfinishingphotos_2, outerfinishingphotos_3.
// _main_photo image an image.
// here i made if statements to determine which file came from which input file
if( $info == $files["innerfinishingphotos_".$i] && $info["name"] == $files["innerfinishingphotos_".$i]["name"] && !empty( $info["name"] ) )
{
$filename = "inner_finishing".$_pId.uniqid().$files["innerfinishingphotos_".$i]["name"];
$upload->addFilter('Rename', $filename, $files["innerfinishingphotos_".$i]);
$photodata = Array ("project_id"=> $_pId, "photo_link"=> "/projects/".$_pId."/".$filename, "photo_name"=> "inner_finishing");
$projectModel->addInProjectGalary($photodata);
$i++;
}
else if( $info == $files["outerfinishingphotos_".$g] && $info["name"] == $files["outerfinishingphotos_".$g]["name"] &&!empty( $info["name"] ) )
{
$filename = "outer_finishing".$_pId.uniqid().$files["outerfinishingphotos_".$g]["name"];
$upload->addFilter('Rename', $filename, $files["outerfinishingphotos_".$g]);
$photodata = Array ("project_id"=> $_pId, "photo_link"=> "/projects/".$_pId."/".$filename, "photo_name"=> "outer_finishing");
$projectModel->addInProjectGalary($photodata);
$g++;
}
else if ($info == $files["_main_photo"] && !empty( $info["name"] ))
{
$filename = "main_photo".$_pId.uniqid().$files["_main_photo"]["name"];
$upload->addFilter('Rename', $filename, $files["_main_photo"]);
$photodata = Array ("project_id"=> $_pId, "photo_link"=> "/projects/".$_pId."/".$filename, "photo_name"=> "project_photo");
$projectModel->addInProjectGalary($photodata);
}
//then i receive the image
if($upload->isValid($file))
{
try {
$upload->receive($file);
}
catch (Exception $e) {
echo "upload exteption";
}
}
}
i tested this code and i works correctly on localhost and all images uploaded and their data entered my database
but on my remote host 'ipage.com' not work.
please guys help me
after many hours trying, i solved the problem , it wase in this line
$upload->setDestination('projects\\'.$_pId);
changing it to
$upload->setDestination('projects/'.$_pId);
thank you mr. Tim Fountain

Can't move/fine APC Uploaded file

As a bit of a follow up to Javascript form won't submit (to view the code I am using visit that link) I am now encountering a problem that I cannot find the file that has been uploaded.
I have added $files = apc_fetch('files_'.$_POST['APC_UPLOAD_PROGRESS']); to the top of my page and this is the output of print_r($files);
Array
(
[theFile] => Array
(
[name] => tt1.mp4
[type] => video/mp4
[tmp_name] => /tmp/php2BEvy7
[error] => 0
[size] => 1050290
)
)
However when I try to run the following code:
if (file_exists($files['theFile']['tmp_name'])) {
$webinarType = strcmp($files['theFile']['type'], 'video/mp4');
if($webinarType == 0) {
$webinarFile = $fileTitle;
$webinarTempName = $files['theFile']['tmp_name'];
} else {
echo 'Webinar must be .mp4';
}
} else {
echo "No File";
}
I get the No File output.
I have ssh'd into the server and the file is not in /tmp/, /path/to/public_html/tmp/ or path/to/file/tmp/ all of which exist.
I have tried to use move_uploaded_file() but as this is executed on all file inputs I can't get the tmp_name dynamically due to my limited knowledge of javascript.
tl;dr version; Where is my file gone and how can I find it?
NOTE; This form did work before the APC intevention and I am running wordpress in case that affects anything.
Fixed this one on my own as well.
In the progress.php file (found on the other question) I modified the elseif statement with this:
elseif(($s_progressId = $_POST['APC_UPLOAD_PROGRESS']) || ($s_progressId = $_GET['APC_UPLOAD_PROGRESS']))
{
// If the file has finished uploading add content to APC cache
$realpath = realpath($PHP_SELF);
$uploaddir = $realpath . '/tmp/';
foreach ($_FILES as $file) {
if(!empty($file['name'])) {
$uploaded_file = $file['name'];
$moveme = $uploaddir.$uploaded_file;
move_uploaded_file($file['tmp_name'], $moveme);
}
}
apc_store('files_'.$s_progressId, $_FILES);
die();
}
That way I could iterate through the $_FILES array without knowing the name of the input. I noticed that it loops through a couple of times hence the if(!empty()) however in hindsight it's probably best practice anyway.

Categories