I want to edit certain parts of a file before it gets downloaded. I want to do it via php, but i can live with javascript or flash. How wold i do it?
this is how i tried it, but it replaces the whole line and also doesnt revert back to the original
<?php
$file = 'folder/file.ext';
if($_POST['filename'] != null)
{
$exclude = "text";
$lines = file($file);
$out = $_POST['filename'];
foreach ($lines as $line) {
if (strstr($line, $exclude) == "") {
$out .= $line;
}
}
$f = fopen($file, "w");
fwrite($f, $out);
fclose($f);
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="text.php"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
$exclude = $_POST['filename'];
$lines = file($file);
$out = "text";
foreach ($lines as $line) {
if (strstr($line, $exclude) == "") {
$out .= $line;
}
}
$f = fopen($file, "w");
fwrite($f, $out);
fclose($f);
}
}
?>
For this you want to learn about a few things. The first being mod_rewrite, which allows "URL Rewriting". What you can do with this, is you can make it so that when a user tried to access "http://example.com/files/file-123.txt", instead they get "http://example.com/download.php?file=file-123.txt". They won't know that they're hitting the PHP Script, but they do.
Using this, on download.php, you can do something like
$file = $_GET['file'];
if (file_exists($file))
{
//Put your headers here
$contents = file_get_contents($pathToFile);
//Do your replacements in $contents here, but don't write to the file
echo $contents;
}
And that way you're only modifying the file that gets sent to the user, not the file that's on your server itself.
Keep in mind that this doesn't outlay any security issues that you'll need to fix. There are a lot of them when you're doing file access, such as making sure that $_GET['file'] is a file that they're actually allowed to access, and not say "/etc/sudoers".
But I think this is the approach that you'd like to take, yes?
I think you have to download file and then modify it and save.
To read particular part of the file use fgets($file, position)
If you want to place content in particular position try fseek()
If you want just append file_put_content($file, $content, FILE_APPEND);
Related
I am trying to output an array to CSV with PHP using the below code. It is, however outputting the entire HTML page to the CSV. How can I write this so it only outputs the array to the CSV and not the code of the page?
I believe the problem is to do with:
$f = fopen('php://output', 'w');
function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
// open raw memory as file so no temp files needed, you might run out of memory though
$f = fopen('php://output', 'w');
// loop over the input array
foreach ($array as $line) {
// generate csv lines from the inner arrays
fputcsv($f, $line, $delimiter);
}
// reset the file pointer to the start of the file
fseek($f, 0);
// tell the browser it's going to be a csv file
header('Content-Type: application/csv');
// tell the browser we want to save it instead of displaying it
header('Content-Disposition: attachment; filename="'.$filename.'";');
// make php send the generated csv lines to the browser
fpassthru($f);
}
array_to_csv_download($data_array);
You are sending output before your headers.
You can simplify to:
<?php
function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="'.$filename.'";');
$f = fopen('php://output', 'w');
foreach ($array as $line)
fputcsv($f, $line, $delimiter);
}
Make sure you do not output anything else prior to those header calls.
I want to copy an entire php file into a csv file and download it, but the demo.csv file that I get is empty. Why am I getting an empty file?
The data in the php file is stored per line.
<?php
// output headers so that the file is downloaded rather than displayed
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename="demo.csv"');
// do not cache the file
header('Pragma: no-cache');
header('Expires: 0');
$handle = fopen("caldataprog.php", "r"); //fileurl
$lines = [];
if (($handle = fopen("caldataprog.php", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, "\t")) !== FALSE) {
$lines[] = $data;
}
fclose($handle);
}
$fp = fopen('demo.csv', 'w');
foreach ($lines as $line) {
fputcsv($fp, $line);
}
fclose($fp);
?>
What I see is that you finally copy a file to other and don't flush this last.
<?php
$source = 'caldataprog.php'; // Presuming it contains raw CSV
$destination = 'demo.csv';
copy($source, $destination);
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="demo.csv"');
readfile($destination); // Send file to user
If caldataprog.php generates CSV and you want to copy the result, you can do :
$source = 'http://yourwebsite.net/caldataprog.php';
$destination = 'demo.csv';
copy($source, $destination);
You are writing the output data to a file named demo.csv on your server, and you are downloading a file named demo.csv in your browser, but they are not the same file.
If you want to download the file in your browser, you need to have PHP output the file's contents.
You could do this using readfile, or by just using echo while you are reading the original input file (and never save the local demo.csv on the server's disk).
I'm using the following code to download files. When I use this code with small files, it works. But if I just point to to a large file ~2GB, the same code fails to download the large file.
$file_name = 'myfile.tar.gz';
$file_url = $base_url.'/sites/default/files/vss/Windows/myfile.tar.gz';
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"".$file_name."\"");
readfile($file_url);
Any clue will help.
UPDATE:
I was able to run using chunked files but I'm still NOT able to open the archive file that is downloaded. I tried multiple times but every time I get the same error:
Cannot open the file as [gzip] archive
Is not an archive
the code which I'm using is:
// Read a file and its content chunk by chunk
function readfile_chunked($filename, $retbytes = TRUE) {
$buffer = '';
$cnt = 0;
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, CHUNK_SIZE);
echo $buffer;
ob_flush();
flush();
if ($retbytes) {
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;
}
I'm creating a CSV from an array. The problem is that I dont want to download it but I want to save it to a folder in my server. This is my function
protected function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
header('Content-Type: application/csv; charset=utf-8');
header('Content-Disposition: attachement; filename="'.$filename.'";');
$f = fopen('php://output', 'w');
foreach ($array as $line) {
fputcsv($f, $line, $delimiter);
}
}
How can I make it so that it saves it to the server? Thanks!
Remove headers.
Use you server's file path in fopen handle.
$f = fopen('path of file on server ', 'w');
I'm trying to combine two CSV files in PHP. I'm looking for perfect method. Here's my code so far:
$one = fopen('data5.csv', 'r');
$two = fopen('userdata.csv', 'r');
$final = fopen('final_data.csv', 'a');
$temp1 = fread($one, filesize("data5.csv"));
$temp2 = fread($two, filesize("userdata.csv"));
fwrite($final, $temp1);
fwrite($final, $temp2);
I will give you a solution to use if you have big CVSs and you don't want to use much of your machine's RAM (imagine each CSV is 1GB, for example).
<?php
function joinFiles(array $files, $result) {
if(!is_array($files)) {
throw new Exception('`$files` must be an array');
}
$wH = fopen($result, "w+");
foreach($files as $file) {
$fh = fopen($file, "r");
while(!feof($fh)) {
fwrite($wH, fgets($fh));
}
fclose($fh);
unset($fh);
fwrite($wH, "\n"); //usually last line doesn't have a newline
}
fclose($wH);
unset($wH);
}
Usage:
<?php
joinFiles(array('join1.csv', 'join2.csv'), 'join3.csv');
Fun fact:
I just used this to concat 2 CSV files of ~500,000 lines each. It took around 5seconds and used 512kb of memory.
Logic:
Open each file, read one line and then write it to the output file. Yes, it may be slower writing each line rather than writing a whole buffer, but this allows the usage of heavy files while being gentle on the memory of the machine.
At any point, you are safe because the script only reads on line at a time and then writes it.
Enjoy!
How about...
file_put_contents('final_data.csv',
file_get_contents('data5.csv') .
file_get_contents('userdata.csv')
);
Note that this loads the entire files into PHP memory though. So, if they are big, you may get memory_limit issues.
If you want to just concatenate the two files you can do this easily with executing a shell script assuming you are on unix like os:
exec("cat data5.csv > final_data.csv && cat userdata.csv >> final_data.csv");
ob_start();
$dir1 = "csv/2014-01/";
$dir = $_REQUEST['folder_name'];
$totalfiles = count(glob($dir."/*",GLOB_BRACE));
echo "Total files in folder = ".$totalfiles;
if ($opend = opendir($dir)){
$i =0; $final_array_export= array();
$fil_csv =end(explode('/',$dir));
$file_name = 'download/'.$fil_csv.'.csv';
$file_cre = fopen($file_name,"w");
$headers = array("header1","header2");
fputcsv($file_cre,$headers);
while (($file = readdir($opend)) !== false){
$filename = $dir.'/'.$file;
$files = fopen($filename,"r");
if($files){
$fullarray = fgetcsv($files);
$head=array();
if(count($fullarray) >0){
foreach($fullarray as $headers){
$head[] = $headers;
}
}
while($data = fgetcsv($files,0,",")){
if(count($data) >0 && count($head) >0){
$array_combine = array_combine($head,$data);
}
fputcsv($file_cre,$array_combine);
}
}
}
fclose($file_cre);
header("Content-Type: application/force-download");
header("Content-type: application/csv");
header('Content-Description: File Download');
header('Content-Disposition: attachment; filename=' . $file_name);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-length: ' . filesize($file_name));
ob_clean();
flush();
readfile($file_name);
}