I have this annoying problem:
Below you will see my messy upload script in which, whenever I upload a video file, I use a md5 function to name it so there are no video files with the same names in my database/folder.
The problem is that when I upload a given file multiple times to the database, it gets stored with the same md5 file name every time. I would really appreciate it if you could help me fix this little bug. I may be tired or something. I tried a hundred different solutions, and nothing fixed it.
Here is my mess:
<?php
class Upload_model extends CI_Model {
var $gallery_path;
var $videos_path;
var $thumbnail;
var $video_name;
var $upload_data;
var $file_name;
var $name;
var $videos_folder = "http://localhost/upload/videos/";
//////////////////////////////
function Upload_model() {
parent::__construct();
$this->videos_path = realpath(APPPATH . '..\videos');
// $this->returnFromDatabase();
}
function do_upload() {
$name = $_FILES['userfile']['name']; // get file name from form
$fileNameParts = explode(".", $name); // explode file name to two part
$fileExtension = end($fileNameParts); // give extension
$fileExtension = strtolower($fileExtension); // convert to lower case
$encripted_pic_name = md5($name) . "." . $fileExtension; // new file name
$config['file_name'] = $encripted_pic_name; //set file name
$config = array(
'allowed_types' => 'avi|mp4|flw|mov',
'upload_path' => $this->videos_path,
'file_name' => $encripted_pic_name
);
$this->load->library('upload', $config);
if ($this->upload->do_upload()) {
$this->upload_data = $this->upload->data(); //Returns array of containing all of the data related to the file you uploaded.
$this->file_name = $this->upload_data['file_name'];
$this->getThumbImage('C:\\xampp\\htdocs\\upload\\videos\\' . $encripted_pic_name);
$insert_data = array(
'name' => $encripted_pic_name,
'path' => 'C:\\xampp\\htdocs\\upload\\videos\\' . $encripted_pic_name,
'thumb_path' => 'C:\\xampp\\htdocs\\upload\\videos\\' . $encripted_pic_name . "_t.jpeg",
'uploaded_by' => 'admin'
);
$this->db->insert('videos', $insert_data); //load array to database
redirect('/welcome');
}
}
function getVideoInformation($videoPath) {
$movie = new ffmpeg_movie($videoPath, false);
$this->videoDuration = $movie->getDuration();
$this->frameCount = $movie->getFrameCount();
$this->frameRate = $movie->getFrameRate();
$this->videoTitle = $movie->getTitle();
$this->author = $movie->getAuthor();
$this->copyright = $movie->getCopyright();
$this->frameHeight = $movie->getFrameHeight();
$this->frameWidth = $movie->getFrameWidth();
$this->pixelFormat = $movie->getPixelFormat();
$this->bitRate = $movie->getVideoBitRate();
$this->videoCodec = $movie->getVideoCodec();
$this->audioCodec = $movie->getAudioCodec();
$this->hasAudio = $movie->hasAudio();
$this->audSampleRate = $movie->getAudioSampleRate();
$this->audBitRate = $movie->getAudioBitRate();
}
function getAudioInformation($videoPath) {
$movie = new ffmpeg_movie($videoPath, false);
$this->audioDuration = $movie->getDuration();
$this->frameCount = $movie->getFrameCount();
$this->frameRate = $movie->getFrameRate();
$this->audioTitle = $movie->getTitle();
$this->author = $movie->getAuthor();
$this->copyright = $movie->getCopyright();
$this->artist = $movie->getArtist();
$this->track = $movie->getTrackNumber();
$this->bitRate = $movie->getBitRate();
$this->audioChannels = $movie->getAudioChannels();
$this->audioCodec = $movie->getAudioCodec();
$this->audSampleRate = $movie->getAudioSampleRate();
$this->audBitRate = $movie->getAudioBitRate();
}
function getThumbImage($videoPath) {
$movie = new ffmpeg_movie($videoPath, false);
$this->videoDuration = $movie->getDuration();
$this->frameCount = $movie->getFrameCount();
$this->frameRate = $movie->getFrameRate();
$this->videoTitle = $movie->getTitle();
$this->author = $movie->getAuthor();
$this->copyright = $movie->getCopyright();
$this->frameHeight = $movie->getFrameHeight();
$this->frameWidth = $movie->getFrameWidth();
$capPos = ceil($this->frameCount / 4);
if ($this->frameWidth > 120) {
$cropWidth = ceil(($this->frameWidth - 120) / 2);
} else {
$cropWidth = 0;
}
if ($this->frameHeight > 90) {
$cropHeight = ceil(($this->frameHeight - 90) / 2);
} else {
$cropHeight = 0;
}
if ($cropWidth % 2 != 0) {
$cropWidth = $cropWidth - 1;
}
if ($cropHeight % 2 != 0) {
$cropHeight = $cropHeight - 1;
}
$frameObject = $movie->getFrame($capPos);
if ($frameObject) {
$imageName = $this->file_name . "_t.jpeg";
$tmbPath = "C:\\xampp\\htdocs\\upload\\videos\\" . $imageName;
$frameObject->resize(120, 90, 0, 0, 0, 0);
imagejpeg($frameObject->toGDImage(), $tmbPath);
} else {
$imageName = "";
}
return $imageName;
}
}
For what matters, CI's upload class has a property called encrypt_name. You can set it to true and have your filename encrypted by default without you doing something else. Take a look: http://ellislab.com/codeigniter/user-guide/libraries/file_uploading.html
Also, since you are using CI, please use the Upload Class, don't write your own when the one provided from CI is so easy to use.
md5 will always return the same value when used on the same string, so uploading the file with the same name will end up with the same hash, add a random string to the file name
$encripted_pic_name = md5(microtime() . $name) . '.' . $fileExtension
You also need to be aware that clashes can happen with md5() where two different strings will have the same output. I wouldn't worry about this too much though for your needs.
You'll need to attach some random characters to the name before you md5 it (though even then it'll still have the chance of a duplicate name).
E.g:
$encripted_pic_name = md5($name . $randomStringHere) . "." . $fileExtension; // new file name
md5 will always give the same output for the same input, so if you upload the same file twice, then yes, you have already used that hash.
If you just want random names, then you don't even need to use MD5 and could just dynamically create a random string everytime a file is uploaded (a, b, c, etc to z, then aa, ab, ac, etc).
If the file name is same then it will return the same md5 hash
For this you have to encrypt unique name or number
You can use
$encripted_pic_name = md5(strtotime()) . "." . $fileExtension; // new file name
or
$encripted_pic_name = md5(uniqid()) . "." . $fileExtension; // new file name
Related
I'm trying to upload 4 images, but I have a problem with their names. When I am saving images in my server, I save their names in an array, but it only returns the attribute of the first image and the rest is only the name (without attribute). Also, in the rest it only returns the letter of that index.
I'm really confused, why is that happening?
My file names are: pictts.jpeg / picture.jpeg / adadas.jpeg / b.jpeg
$img_counter = count($_FILES['upload_img']['name']);
$files = $_FILES;
for ($i = 0; $i < $img_counter; $i++) {
$this->load->library('upload');
$my_file_name = time() . $_FILES['upload_img']['name'][$i];
$my_new_file_name = str_replace(' ', '_', $my_file_name);
$my_new_file_names = str_replace('-', '_', $my_new_file_name);
$New_file_name = $my_new_file_names;
$_FILES['upload_img']['name'] = $files['upload_img']['name'][$i];
$_FILES['upload_img']['type'] = $files['upload_img']['type'][$i];
$_FILES['upload_img']['tmp_name'] = $files['upload_img']['tmp_name'][$i];
$_FILES['upload_img']['error'] = $files['upload_img']['error'][$i];
$_FILES['upload_img']['size'] = $files['upload_img']['size'][$i];
$this->upload->initialize($this->upload_options($New_file_name));
$upload_res [] = $this->upload->do_upload('upload_img');
$error[] = $this->upload->display_errors();
$upload_data[] = $New_file_name;
}
Wrong result:
i have a php code that works great everything is fine. all images are uploadet to server and also store info in database. BUT i have decided to add time to each uploaded file right before file extension and also want to store that information in database.
This is my code:
<?php
function jaunProd() {
include 'database.php';
$message = '';
if (isset($_POST['jaunProdPoga'])) {
if(!empty($_POST['prod_vards']) && !empty($_POST['kat_id']) && !empty($_POST['subkat_id']) && !empty($_POST['prod_apraksts']) ){
$prod_vards = $_POST['prod_vards'];
$kat_id = $_POST['kat_id'];
$subkat_id = $_POST['subkat_id'];
$name_array = $_FILES['file_array']['name'];
$tmp_name_array = $_FILES['file_array']['tmp_name'];
$type_array = $_FILES['file_array']['type'];
$size_array = $_FILES['file_array']['size'];
$error_array = $_FILES['file_array']['error'];
for ($i=0; $i <count($tmp_name_array); $i++){
move_uploaded_file($tmp_name_array[$i],'img/prod_img/'.time().$name_array[$i]);
}
$prod_kods = $_POST['prod_kods'];
$prod_cena = $_POST['prod_cena'];
$prod_apraksts = $_POST['prod_apraksts'];
$stmt=$conn->prepare("INSERT INTO produkti (prod_vards, kat_id, subkat_id, prod_img1, prod_img2, prod_img3, prod_img4, prod_img5, prod_kods, prod_cena, prod_apraksts) VALUES ('$prod_vards', '$kat_id', '$subkat_id', '$name_array[0]', '$name_array[1]', '$name_array[2]', '$name_array[3]', '$name_array[4]', '$prod_kods', '$prod_cena', '$prod_apraksts')");
if($stmt->execute()){
$message = '<p class="green">Produkts pievienots </p>';
} else {
$message = '<p class="red">SEIT LAIKA MIR KLIASHF </p>';
}
} else {
$message = '<p class="red">Lauki ar * nedrīkst būt tukši! </p>';
}
}
echo $message;
}
?>
Here move_uploaded_file($tmp_name_array[$i],'img/prod_img/'.time().$name_array[$i]);
i add time to file but this adds to front of file, but how to add after name and before extension.
And also i dont know how to store that dynamical info in database.
Thanks for help.
<?php
$ImageName = str_replace(' ', '-', strtolower($_FILES['myfile']['name']));
$ImageExt = substr($ImageName, strrpos($ImageName, '.'));
$ImageExt = str_replace('.', '', $ImageExt);
$ImageName = preg_replace("/\.[^.\s]{3,4}$/", "", $ImageName);
$NewImageName = $ImageName .time(). '.' . $ImageExt;
move_uploaded_file($tmp_name_array[$i],'img/prod_img/'.$NewImageName);
?>
I need to upload files and folders into a course in moodle from a zip file, I have been searching and I found how to upload files. I try to upload, and the files are uploaded correctly into the database and in the file repository, but this files are not showed in the course when I enter to the course.
The code below is what I trying
$packer = get_file_packer('application/zip');
$files = $packer->extract_to_pathname($archivo_zip, $carpeta_unzip );
foreach($files as $path => $status){
$fs = get_file_storage();
$context = context_course::instance($courseid);
$filename = basename($path);
$path_directory = "/" . str_replace($filename, "", $path);
$author = $DB->get_record('user', array('id'=>$userid ), '*', MUST_EXIST);
$file_record = new stdClass;
$file_record->component = 'mod_folder'; //mod_resource
$file_record->contextid = $context->id;
$file_record->userid = $userid ;
$file_record->filearea = 'content'; //draft, attachment
$file_record->filename = $filename;
$file_record->filepath = $path_directory;
$file_record->itemid = 0;
$file_record->author = fullname($author);
$file_record->license = $CFG->sitedefaultlicense;
$file_record->source = $filename;
//$file_record->timecreated = time();
//$file_record->timemodified = time();
$existingfile = $fs->file_exists($file_record->contextid, $file_record->component, $file_record->filearea,
$file_record->itemid, $file_record->filepath, $file_record->filename);
if ($existingfile) {
//throw new file_exception('filenameexist');
} else {
$stored_file = $fs->create_file_from_pathname($file_record, $path_upload);
}
}
I try to upload the files manually through the website and I've noticed that the folders ara created in another table called mdl_folder or in the table called mdl_file, but i don't know how do that and the best way to create and relate folders with files programatically for then displayed in the website well.
So if anyone knows how to do it or have any examples or documentation that may be useful, it would be helpful.
Thanks in advance.
I found a solution that works for me, I don't know if it is the most appropriate or not, if someone can take a look and tell me if it is correct or not, or what changes could make would be grateful.
The solution i found is:
Create or get it back the folder who will contain the files
Upload the files
Code:
$packer = get_file_packer('application/zip');
$files = $packer->extract_to_pathname($archivo_zip, $carpeta_unzip );
foreach($files as $path => $status){
$fs = get_file_storage();
$folder = get_folder($courseid, 'Upload Test');
$filename = basename($path);
$path_directory = "/" . str_replace($filename, "", $path);
$author = $DB->get_record('user', array('id'=>$userid ), '*', MUST_EXIST);
$file_record = new stdClass;
$file_record->component = 'mod_folder'; //mod_resource
$file_record->contextid = $folder->id;
$file_record->userid = $userid ;
$file_record->filearea = 'content'; //draft, attachment
$file_record->filename = $filename;
$file_record->filepath = $path_directory;
$file_record->itemid = 0;
$file_record->author = fullname($author);
$file_record->license = $CFG->sitedefaultlicense;
$file_record->source = $filename;
//$file_record->timecreated = time();
//$file_record->timemodified = time();
$existingfile = $fs->file_exists($file_record->contextid, $file_record->component, $file_record->filearea,
$file_record->itemid, $file_record->filepath, $file_record->filename);
if ($existingfile) {
//throw new file_exception('filenameexist');
} else {
$stored_file = $fs->create_file_from_pathname($file_record, $path_upload);
}
}
And the function to create or get it back the folder is:
function get_folder($courseid, $resource_name) {
global $DB, $CFG;
//Comprobamos si la carpeta ya existe ya existe
$sql = "SELECT cm.id as cmid FROM {course_modules} cm, {folder} res
WHERE res.name = '" . $resource_name . "'
AND cm.course = " . $courseid . "
AND cm.instance = res.id";
if (! $coursemodule = $DB->get_record_sql($sql)) {
require_once($CFG->dirroot.'/course/lib.php');
echo "\tCreate new folder\n";
$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
// get module id
$module = $DB->get_record('modules', array('name' => 'folder'), '*', MUST_EXIST);
// get course section
/*course_create_sections_if_missing($course->id, 0);
$modinfo = get_fast_modinfo($course->id);
$cw = $modinfo->get_section_info(0);
echo "section id: " . $cw->id;*/
$sectionid = $DB->get_record('course_sections', array('course' => $course->id, 'name' => 'Recursos'), '*', MUST_EXIST);
$folder_data = new stdClass();
$folder_data->course = $course->id;
$folder_data->name = $resource_name;
$folder_data->intro = '<p>'.$resource_name.'</p>';
$folder_data->introformat = 1;
$folder_data->revision = 1;
$folder_data->timemodified = time();
$folder_data->display = 0;
$folder_data->showexpanded = 1;
$folder_data->showdownloadfolder = 1;
$folder_id = $DB->insert_record('folder', $folder_data);
echo "folder id: " . $folder_id;
// add course module
$cm = new stdClass();
$cm->course = $courseid;
$cm->module = $module->id; // should be retrieved from mdl_modules
$cm->instance = $folder_id; // from mdl_resource
$cm->section = $sectionid->id; // from mdl_course_sections
$cm->visible = 1;
$cm->visibleold = 1;
$cm->showavailability = 1;
$cm->added = time();
$cmid = $DB->insert_record('course_modules', $cm);
// add module to course section so it'll be visible
if ($DB->record_exists('course_sections', array('course' => $courseid, 'section' => 1))) {
$sectionid = $DB->get_record('course_sections', array('course' => $courseid, 'section' => 1));
// if sequence is not empty, add another course_module id
if (!empty($sectionid->sequence)) {
$sequence = $sectionid->sequence . ',' . $cmid;
} else {
// if sequence is empty, add course_module id
$sequence = $cmid;
}
$course_section = new stdClass();
$course_section->id = $sectionid->id;
$course_section->course = $courseid;
$course_section->section = 1;
$course_section->sequence = $sequence;
$csid = $DB->update_record('course_sections', $course_section);
} else {
$sequence = $cmid;
$course_section = new stdClass();
$course_section->course = $courseid;
$course_section->section = 1;
$course_section->sequence = $sequence;
$csid = $DB->insert_record('course_sections', $course_section);
}
rebuild_course_cache($courseid, true);
// get context again, this time with all resources present
$context = get_folder($courseid, $resource_name);
return $context;
} else {
$context = context_module::instance($coursemodule->cmid);
return $context;
}
} // get_folder
I have a folder that contains files named standard_xx.jpg (xx being a number)
I would like to find the highest number so that I can get the filename ready to rename the next file being uploaded.
Eg. if the highest number is standard_12.jpg
$newfilename = standard_13.jpg
I have created a method to do it by just exploding the file name but it isn't very elegant
$files = glob($uploaddir.'test-xrays-del/standard_*.JPG');
$maxfile = $files[count($files)-1];
$explode = explode('_',$maxfile);
$filename = $explode[1];
$explode2 = explode('.',$filename);
$number = $explode2[0];
$newnumber = $number + 1;
$standard = 'test-xrays-del/standard_'.$newnumber.'.JPG';
echo $newfile;
Is there a more efficient or elegant way of doing this?
I'd do it like this myself:
<?php
$files = glob($uploaddir.'test-xrays-del/standard_*.JPG');
natsort($files);
preg_match('!standard_(\d+)!', end($files), $matches);
$newfile = 'standard_' . ($matches[1] + 1) . '.JPG';
echo $newfile;
You can make use of sscanfDocs:
$success = sscanf($maxfile, 'standard_%d.JPG', $number);
It will allow you to not only pick out the number (and only the number) but also whether or not this worked ($success).
Additionally you could also take a look into natsortDocs to actually sort the array you get back for the highest natural number.
A complete code-example making use of these:
$mask = 'standard_%s.JPG';
$prefix = 'test-xrays-del';
$glob = sprintf("%s%s/%s", $uploaddir, $prefix, sprintf($mask, '*'));
$files = glob($glob);
if (!$files) {
throw new RuntimeException('No files found or error with ' . $glob);
}
natsort($files);
$maxfile = end($files);
$success = sscanf($maxfile, sprintf($mask, '%d'), $number);
if (!$success) {
throw new RuntimeException('Unable to obtain number from: ', $maxfile);
}
$newnumber = $number + 1;
$newfile = sprintf("%s/%s", $prefix, sprintf($mask, $newnumber));
Try with:
$files = glob($uploaddir.'test-xrays-del/standard_*.JPG');
natsort($files);
$highest = array_pop($files);
Then get it's number with regex and increase value.
Something like this:
function getMaxFileID($path) {
$files = new DirectoryIterator($path);
$filtered = new RegexIterator($files, '/^.+\.jpg$/i');
$maxFileID = 0;
foreach ($filtered as $fileInfo) {
$thisFileID = (int)preg_replace('/.*?_/',$fileInfo->getFilename());
if($thisFileID > $maxFileID) { $maxFileID = $thisFileID;}
}
return $maxFileID;
}
How is the best way to store files linked with a database where not too many files are stored in the same directory (slowing down FTP browsing etc)
My own proposal:
3000000/0/70000/9000/100/30/3079138.full.pdf
3000000/0/70000/9000/100/30/3079138.thumb.png
3000000/0/70000/8000/900/20/3078928.full.png
3000000/0/70000/8000/900/20/3078928.thumb.pdf
3000000/0/70000/8000/900/20/3078929.full.pdf
3000000/0/70000/8000/900/20/3078929.thumb.png
With this solution there will always be a maximum of 10 files (id's) in each directory
With files (id's) ranging from 1 to 1999 the directories in the root will look like this:
create path for an ID
require_once 'File_structure.php';
for($i=1; $i<2000; $i++){
$File = new File_structure();
$File->id = $i;
$File->prepend_path = 'image/';
$path = $File->create();
file_put_contents($path.$i, 'sd');
}
get path for an ID
require_once 'File_structure.php';
$id = 1254;
$File = new File_structure();
$File->id = $id;
$File->prepend_path = 'image/';
$path = $File->get();
if(is_file($path.$id)){
echo 'ok';
}
class
class File_structure {
public $id;
public $prepend_path = '';
private $path = array();
function get(){
$this->path();
return $this->prepend_path.(substr($this->prepend_path, -1) == '/' ? '':'/').implode('/', $this->path).'/';
}
function create(){
$this->path();
$path = substr($this->prepend_path, -1) == '/' ? substr($this->prepend_path, 0, -1):$this->prepend_path;
foreach($this->path as $dir){
$path .= '/'.$dir;
if(!is_dir($path)){
mkdir($path);
chmod($path, 0777);
}
}
return $path.'/';
}
function path(){
$this->prepare_id();
$length = strlen($this->id);
for($i=0; $i<$length; $i++){
$len = $length - $i;
if($len <= 1){
break;
}
if($path = (int)str_pad($this->id[$i], $len, 0, STR_PAD_RIGHT)){
$this->path[] = $path;
}
}
}
function prepare_id(){
$this->id = (string)$this->id;
}
}
Usually i store files based on a simple pattern thats easy to work with:
uploads/<year>/<month>/<day>/full.pdf
uploads/<year>/<month>/<day>/thumb.png
where i naturally check for filename collisions and correct them