Currently I am working on a media uploader system.
When a user uploads files, I wanted the system to automatically check whether this file already exists, and if so, add a (x) to the basename.
DSC_2193.jpg would become DSC_2193 (1).jpg
DSC_2193 (2).jpg would become DSC_2193 (3).jpg
So I came up with the following function:
<?php
private function setFileName($path)
{
if (file_exists($path)) {
$file = pathinfo($path);
if (preg_match('/\(([0-9]+)\).' . $file['extension'] . '/', $file['basename'], $matches)) {
return $this->setFileName($file['dirname'] . '/' . preg_replace_callback('/\(([0-9]+)\).' . $file['extension'] . '/', function($matches)
{
return '(' . ($matches[1] + 1) . ')';
}, $file['basename']) . '.' . $file['extension']);
} else {
$basename = substr(basename($path, $file['extension']), 0, -1);
$basename .= ' (1).' . $file['extension'];
return $this->setFileName($file['dirname'] . '/' . $basename);
}
}
else
return $path;
}
?>
Now I was wondering: would this be the right approach to achieve this? If not: maybe someone can come up with a better alternative. If it is the most efficient way, maybe someone benefits from this.
You can do it easily using while cycle. Here is simple scratch:
private function setFileName($path)
{
$file = pathinfo($path);
if (file_exists($path)) {
$i = 1;
while (file_exists($file['filename'] . ' (' . $i . ').' . $file['extension'])) $i++;
$filename = $file['filename'] . ' (' . $i . ').' . $file['extension']; // don't know if you want also directory path
}
else
$filename = $file['filename'] . '.' . $file['extension'];
// some code to rename/move_uploaded_file...
}
I don't know what you want then if you have $filename set (move_uploaded_file, or just return $filename), so the rest of code is up to you.
Related
I have been trying to modify an XML document within an archived .tgz file by using the PharData class using php. I have no problem modifying the XML through DomDocument class, but I am having a hard time saving the whole process: I end up saving 2 different .phar documents alltogether, w/o modifying anything in the .tgz archive :
folder example image
Here is the code I have been using :
$phar = new PharData($path . '/' . $idClient . '/' . $tempDate->format('ym') . '/' . $file);
echo $phar . "\n";
$dom = new DOMDocument();
$dom->load ('phar://' . $path . '/' . $idClient . '/' . $tempDate->format('ym') . '/' . $file . '/' . substr($file, 0, -4) . '.xml');
if ($dom === null) continue;
$ids = $dom->documentElement->getElementsByTagName('id');
foreach ($ids as $i_id) {
if ($i_id->nodeValue !== $id) continue;
echo $i_id->nodeValue . "\n";
echo $i_id->nodeName . "\n";
$sensor = $i_id->parentNode;
echo $sensor->nodeName . "\n";
foreach ($sensor->childNodes as $object) {
if ($object->nodeName !== 'type') continue;
echo $object->nodeName . "\n";
echo $object->nodeValue . "\n";
$object->nodeValue = $type;
echo $object->nodeValue . "\n" . "\n";
}
}
$dom->save('phar://' . $path . '/' . $idClient . '/' . $tempDate->format('ym') . '/' . $file . '.phar' . '/' . substr($file, 0, -4) . '.xml');
Im using script to go through content of zipped files and the script just misses some of them
We have multiple ZIP archives on a server where invoices (Flat files) are stored. Im using following code to search though them:
foreach($zip_files as $zip_file){
echo $zip_file . "[" . $counter . "/" . $count . "]\n";
$counter++;
//Opening and reading zip file
$zip_content = zip_open($archive_path . "\\" . $zip_file);
while($file = zip_read($zip_content)){
$filename = zip_entry_name($file);
if(strpos($filename,".rcv")){
$content = zip_entry_read($file,4086);
if(strpos($content, "<MvxEnvelope>")){
if(strpos($content, "<Field>TETINR</Field>")){
$type = "TETINR";
$TINR_position = strpos($content, "<Field>TETINR");
$DIVI_position = strpos($content, "<Field>DIVI");
$TINR = substr($content,($TINR_position + 28), 10);
$DIVI = substr($content,($DIVI_position + 26), 3);
fwrite($map, $zip_file . ";" . $filename . ";" . $DIVI . ";" . $TINR . ";" . $type . "\n");
}
}
}
}
}
I would like the script to go through all files and not to miss some of them. Many thanks in advance
I'm trying to rename all files in a folder, I want the last character before the extension to be removed.
This is the code I'm using:
$sql = 'SELECT * FROM tblphotoseries WHERE photoSerieID = ' . mysql_real_escape_string($photoSerieID) . ' AND FKuID = ' . $_SESSION['uID'];
if($series = GetFromDB($sql)){
foreach ($series as $serie){
$path = '../uploads/' . $serie["FKcatID"] . '/' . $_SESSION['uCode'] . '/' . $serie["seriesCode"] . '';
}
$files = scandir($path);
foreach($files as $file) {
if($file != ".." && $file != "."){
$new_name = explode(".", $file);
$ext = $new_name[1];
$new_name = $new_name[0];
$new_name[strlen($new_name) - 1] = "";
$new_name = $new_name . "." . $ext;
$new_name = (string)$new_name;
echo $file . " -> " . $new_name . "\n\r";
clearstatcache();
if(file_exists($path . '/' . $file)){
echo "file_exists \n\r";
clearstatcache();
if(rename($path . '/' . $file, $path . '/' . $new_name)){
echo "rename successful \n\r";
}else{
echo "rename failed \n\r";
}
}
}
}
}
This outputs the following:
AA04a_.jpg -> AA04a.jpg
file_exists
rename failed
AA04b_.png -> AA04b.png
file_exists
rename failed
AA04c_.png -> AA04c.png
file_exists
rename failed
Can anyone spot what's going wrong here? Privileges are ok, I've tried chmod 0777 on the file before renaming as well, without success.
Thanks,
Rik
SOLVED:
$new_name[strlen($new_name) - 1] = "";
had to be replaced by
$new_name = substr_replace($new_name, '', strlen($new_name) - 1, 1);
So i am trying to upload multiple files at once, but each time i do it is only uploading the last file in the loop for each file upload that i try to do. Ultimately it is only uploading one file to my server that multiple points in my database are referencing.
I have tried executing the upload file function outside of the loop with independent functions and variables but it is still doing it.
My code:
<?php $image_number = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
$image_allowed = array('jpg', 'jpeg', 'gif', 'png');
if (empty($errors) === true) {
foreach ($image_number as $value) {
if (isset($_FILES['story_image_' . $value]) === true) {
if (empty($_FILES['story_image_' . $value]['name']) === false) {
if (in_array(strtolower(end(explode('.', $_FILES['story_image_' . $value]['name']))), $image_allowed) === false) {
$errors[] = 'Incorrect file type for \'Story image ' . $value . '\'. Allowed file types: ' . implode(', ', $image_allowed);
} else if ($_FILES['story_image_' . $value]['size'] > 1048576) {
$errors[] = 'Story image ' . $value . '\'s file size may not exceed 1 MB, or 1048576 Bytes.';
}
}
}
}
}
foreach ($image_number as $value) {
if ($_POST['removeImage' . $value] === 'on') {
remove_story_image($story_data['story_id'], $value, $story_data['story_image_' . $value]);
} else {
if (isset($_FILES['story_image_' . $value]) === true) {
if (empty($_FILES['story_image_' . $value]['name']) === false) {
$file_path = '/cdsite/images/storyimages/' . substr(md5(time()), 0, 10) . '.' . strtolower(end(explode('.', $_FILES['story_image_' . $value]['name'])));
$movefile_path = $_SERVER['DOCUMENT_ROOT']."/cdsite/images/storyimages/" . substr(md5(time()), 0, 10) . "." . strtolower(end(explode('.', $_FILES['story_image_' . $value]['name'])));
move_uploaded_file($_FILES['story_image_' . $value]['tmp_name'], $movefile_path);
mysql_query("UPDATE `stories` SET `story_image_" . $value . "` = '" . mysql_real_escape_string($file_path) . "' WHERE `story_id` = " . $story_data['story_id']);
}
}
}
}
?>
I have checked my form, and all of the file fields' names that are independently named and match. It is not a syntax issue because the first loop checking for errors works flawlessly. its only when i try to upload the file does it start to overwrite.
Can anyone enlighten me? ( i am a pretty big noob so please try to keep it in newb speak)
***** Update ***********
So I have solved the problem now and below is the working code:
foreach ($image_number as $value) {
if ($_POST['removeImage' . $value] === 'on') {
remove_story_image($story_data['story_id'], $value, $story_data['story_image_' . $value]);
} else {
if (isset($_FILES['story_image_' . $value]) === true) {
if (empty($_FILES['story_image_' . $value]['name']) === false) {
$file_path = '/cdsite/images/storyimages/' . substr(md5(time()), 0, 10) . '.' . strtolower(end(explode('.', $_FILES['story_image_' . $value]['name'])));
$movefile_path = $_SERVER['DOCUMENT_ROOT']."/cdsite/images/storyimages/" . substr(md5(time()), 0, 10) . "." . strtolower(end(explode('.', $_FILES['story_image_' . $value]['name'])));
if (file_exists($movefile_path) === true) {
$file_path = '/cdsite/images/storyimages/' . substr(md5(time()), 0, 10) . substr(md5(rand()),0,10) . '.' . strtolower(end(explode('.', $_FILES['story_image_' . $value]['name'])));
$movefile_path = $_SERVER['DOCUMENT_ROOT'].$file_path;
}
move_uploaded_file($_FILES['story_image_' . $value]['tmp_name'], $movefile_path);
mysql_query("UPDATE `stories` SET `story_image_" . $value . "` = '" . mysql_real_escape_string($file_path) . "' WHERE `story_id` = " . $story_data['story_id']);
}
}
}
}
For those who may run into a similar problem in the future and need a simple explanation, which i so often appreciate when others provide one, here is a brief explanation of what the issue was and how i fixed it.
The problem was i was md5 hashing the same time when i was iterating through the loop, rewriting over the same file name with this line of code:
$movefile_path = $_SERVER['DOCUMENT_ROOT']."/cdsite/images/storyimages/" . substr(md5(time()), 0, 10) . "." . strtolower(end(explode('.', $_FILES['story_image_' . $value]['name'])));
As you notice i have two file paths. This isn't to confuse anyone, it is to allow me to upload a absolute path to the database that html can reference later ($file_path) and to have an absolute path that php can work with to upload the file ($movefile_path).
To fix the problem i had the loop check to see if the file already exists and, if it did, just added a random string that was md5 hashed following the md5 hashed timestamp to make a new unique file name. I used the $movefile_path file path to check to see if the file existed because that is the path php can use.
I also made sure to include the updated $file_path variable in the updated $movefile_path, otherwise re-hashing the random string would have given me a different file name for html to reference from my database than the actual file name that php uploaded.
You should rename the file you are uploading, never trust user input...
You could put a unix timestamp or unique id behind the image name
But what's the best and easiest way to copy a file or folder between a local and remote server using php? These are files located above the web folder, so I'll need to use paths instead of the URL.
I would do it using PHP's built-in FTP functions.
EDIT: Ahh, you want secure. This is what I would use then: SSH2-SFTP
Well i made this function hope it works for you copy files from ftp:
$ftpConnection = the conection, example ftp_connect(1.0.0.1).
$path = the ftp path.
$destination = the local file.
function ftpRecursiveFileListing($ftpConnection, $path, $destination) {
$contents = ftp_nlist($ftpConnection, $path);
foreach ($contents as $currentFile) {
if (strpos($currentFile, '.') === false) {
$dir = basename($currentFile);
echo "<br> <b> Directorio </b>" . $dir;
mkdir($destination . "/" . $dir);
ftpRecursiveFileListing($ftpConnection, $currentFile, $destination . "/" . $dir);
} else {
$file = basename($currentFile);
echo '<br> <b>archivo </b>' . $file;
echo '<br> <b>path </b>' . $path;
echo '<br> <b>completo </b>' . $path . "/" . $file;
ftp_get($ftpConnection, $destination . '/' . $file, $path . '/' . $file, FTP_BINARY);
}
}
}