PHP load CSV without filename - php

I am in index.php, and at the same directory level I have a CSV file which I load using
$reader = new CSV\CSVReader('mycsv.csv');
This is the only CSV in the folder. After it is read, I want to delete it from my FTP and replace it with a different CSV. However, if possible, I don't want to have to edit the PHP file each time to change the filename.
Knowing that the root will only ever have one CSV file in it at any time, is there any way to load this without using the filename?

You could get all the files with a .csv extension using glob(). Then just use the first file in the result array since there's only one. Something like this:
$csvFiles = glob('*.csv');
if (!count($csvFiles)) die('Error: No CSV file to read');
$reader = new CSV\CSVReader($csvFiles[0]);
// Optionally, if you want to automatically delete the file:
unlink($csvFiles[0]);

Try this
$files = scandir('/path/to/directory');
$filename = $files[2]; // avoid dots elements

Related

PHP - select ONLY file in folder without foreach()?

I have a script that places a CSV file into a temporary folder where it will remain until another script picks it up for import into my DB. This is a separated script and for various reasons cannot do both the placement into the temp folder AND the consecutive database import.
Since I now have a separated import script, I first need to scan the temp folder and look for the import-file, which is the ONLY file in the folder anyway, but has a constantly changing filename that I cannot pre-define. My question now is, how can I get the filename of said file, assign it to a variable and use this later for the database import?
When using a foreach() loop I end up with an array, but rather would like a string for further usage.
PHP
if(file_exists('./'.$temp)) {
$files = scandir('./'.$temp.'/');
foreach ($files as $attachment) {
if (in_array($attachment, array(".",".."))) continue;
$import_file = $attachment;
}
} else {
die("Temp Folder for $temp could not be found, hence no files exist for import. Operation cancelled.");
}
Since scandir is ordered alphabetically (http://php.net/manual/en/function.scandir.php), you file will always be at the end of the scandir array (on non-unix systems it is the only file, on unix systems it comes after . and ..).
Thus, you just need to get the last item of the array, like so:
$s = scandir("./".$temp."/");
$import_file = $s[count($s)-1];
This code automatically retrieves the name of the third file in the temp folder, so as long as there are no other files in there it should work perfectly.

PharData offsetExists on filename prefixed with ".\"

I have a .tar.gz file downloaded from an external API which we have to implement. It contains images for an object.
I'm not sure how they managed to compress it this way, but the files are basically prefixed with the "current directory". It looks like this in WinRAR:
And like this in 7-Zip, note the .tar first level, and "." second level:
-> ->
When calling
$file = 'archive.tar.gz';
$phar = new PharData($file, FilesystemIterator::CURRENT_AS_FILEINFO);
var_dump($phar->offsetGet('./12613_s_cfe3e73.jpg'));
I get the exception:
Cannot access phar file entry '/12613_s_cfe3e73.jpg' in archive '{...}/archive.tar.gz'
Calling a file which does not exist, e.g.:
var_dump($phar->offsetGet('non-existent.jpg'));
Or calling it without the directory seperator, e.g.:
var_dump($phar->offsetGet('12613_s_cfe3e73.jpg'));
I get a
Entry 12613_s_cfe3e73.jpg does not exist
Exception.
It is not possible to get the archive formatted differently. Does anyone have an idea how to solve this?
Ended up using Archive_Tar. There must be something wrong in the source code of PHP, though I don't think this is the "normal" way of packaging a .tar either.
Unfortunately I'm not very good at C, but it's probably in here (line 1214) or here.
This library seems to handle it just fine, using this example code:
$file = 'archive.tar.gz';
$zip = new Archive_Tar($file);
foreach ($zip->listContent() as $file) {
echo $file['filename'] . '<br>';
}
Result:
./12613_s_f3b483d.jpg
./12613_s_cfe3e73.jpg
./1265717_s_db141dc.jpg
./1265717_s_af5de56.jpg
./1265717_s_b783547.jpg
./1265717_s_35b11f9.jpg
./1265716_s_83ef572.jpg
./1265716_s_9ac2725.jpg
./1265716_s_c5af3e9.jpg
./1265716_s_c070da3.jpg
./1265715_s_4339e8a.jpg
Note the filenames are still prefixed with "./" just like they are in WinRAR.
If you want to stick to using PharData, i suggest a more conservative, two-step approach, where you first decompress the gz and then unarchive all files of the tar to a target folder.
// decompress gz archive to get "/path/to/my.tar" file
$gz = new PharData('/path/to/my.tar.gz');
$gz->decompress();
// unarchive all files from the tar to the target path
$tar = new PharData('/path/to/my.tar');
$tar->extractTo('/target/path');
But it looks like you want to select individual files from the tar.gz archive directly, right?
It should work using fopen() with a StreamReader (compress.zlib or phar) and selecting the individual file. Some examples:
$f = fopen("compress.zlib://http://some.website.org/my.gz/file/in/the/archive", "r");
$f = fopen('phar:///path/to/my.tar.gz//file/in/archive', 'r');
$filecontent = file_get_contents('phar:///some/my.tar.gz/some/file/in/the/archive');
Streaming should also work, when using Iterators:
$rdi = new RecursiveDirectoryIterator('phar:///path/to/my.tar.gz')
$rii = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($rii as $splFileInfo){
echo file_get_contents($splFileInfo->getPathname());
}
The downside is that you have to buffer the stream and save it to file.
Its not a direct file extraction to a target folder.

How to dynamically present an on the fly zipfile to users

I'm editing an ancient script that zips several images and presents them dynamically to the user.
I have rewritten almost all of the code, but I can't find a way to way to output the contents of the zipfile. Writing it to the server is very undesirable.
I create the file with:
$z = new ZipArchive();
I can add content with:
$z->addFromString("filename",$string);
And I want to present it dynamically with:
header("Content-Type: application/zip;");
header("Content-Disposition: attachment; filename=file.zip;");
// I need a function to read the contents of the zipfile here. Something like:
echo $z->filecontent();
I can't find out what function to use for this.
You would open the file, creating it most likely with temp name. Something like this:
$name = tempnam('/tmp','zip');
$z->open($name, ZIPARCHIVE::CREATE)
After you finish adding all your files, you would close it.
$z->close();
Now when you are ready to send the data you would do this:
readfile($name);
After you are done, you want to clean up the temp file with:
unlink($name);
If you read the documentation, look at the close() method to actually save the file physically to the filesystem. Then you can use readfile() on the saved file

How to get a temporary file path?

I know you can create a temporary file with tmpfile and than write to it, and close it when it is not needed anymore. But the problem I have is that I need the absolute path to the file like this:
"/var/www/html/lolo/myfile.xml"
Can I somehow get the path, even with some other function or trick?
EDIT:
I want to be able to download the file from the database, but without
$fh = fopen("/var/www/html/myfile.xml", 'w') or die("no no");
fwrite($fh, $fileData);
fclose($fh);
because if I do it like this, there is a chance of overlapping, if more people try to download the same file at exactly the same time. Or am I wrong?
EDIT2:
Maybe I can just generate unique(uniqID) filenames like that, and than delete them. Or can this be too consuming for the server if many people are downloading?
There are many ways you can achieve this, here is one
<?php
// Create a temp file in the temporary
// files directory using sys_get_temp_dir()
$temp_file = tempnam(sys_get_temp_dir(), 'MyFileName');
echo $temp_file;
?>
The above example will output something similar to:
/var/tmp/MyFileNameX322.tmp
I know you can create a temporary file with tmpfile
That is a good start, something like this will do:
$fileHandleResource = tmpfile();
Can I somehow get the path, even with some other function or trick?
Yes:
$metaData = stream_get_meta_data($fileHandleResource);
$filepath = $metaData['uri'];
This approach has the benefit of leaving it up to PHP to pick a good place and name for this temporary file, which could end up being a good thing or a bad thing depending on your needs. But it is the simplest way to do this if you don't yet have a specific reason to pick your own directory and filename.
References:
http://us.php.net/manual/en/function.stream-get-meta-data.php
Getting filename (or deleting file) using file handle
This will give you the directory. I guess after that you are on your own.
For newer (not very new lol) versions of PHP (requires php 5.2.1 or higher) #whik's answer is better suited:
<?php
// Create a temp file in the temporary
// files directory using sys_get_temp_dir()
$temp_file = tempnam(sys_get_temp_dir(), 'MyFileName');
echo $temp_file;
?>
The above example will output something similar to: /var/tmp/MyFileNameX322.tmp
old answer
Just in case someone encounters exactly the same problem. I ended up doing
$fh = fopen($filepath, 'w') or die("Can't open file $name for writing temporary stuff.");
fwrite($fh, $fileData);
fclose($fh);
and
unlink($filepath);
at the end when file is not needed anymore.
Before that, I generated filename like that:
$r = rand();
$filepath = "/var/www/html/someDirectory/$name.$r.xml";
I just generated a temporary file, deleted it, and created a folder with the same name
$tempFolder = tempnam(sys_get_temp_dir(), 'MyFileName');
unlink($tempFolder);
mkdir($tempFolder);

How we can read zip file and get information of files or folders contains without unzipping in PHP?

What I actually wanted to do is read zip file and then if it does contain folder then refuse it with some message.
I want user should upload zip file with files only without any directory structure.
So I want to read zip file contains and check file structure.
I am trying with following code snippet.
$zip = zip_open('/path/to/zipfile');
while($zip_entry = zip_read($zip)){
$filename = zip_entry_name($zip_entry);
//#todo check whether file or folder.
}
I have sorted out.
I am now checking filename as strings wherever I am getting string ending with "/" that am treating as directory else as file.
can't you parse path of $filename? something like $dirName = pathinfo($filename, PATHINFO_DIRNAME)

Categories