When creating a new PHP child thread it becomes unable to delete files using unlink(). is there a good reason for that limitation or I'm forgetting something?
I get a worning:
Warning: unlink(downloads/1e6f6fa1c0552a1af9058f10216b40e8): No such
file or directory
although the file is created in the destination folder, and when I run the same command outside the thread function it deletes the file as it should.
//multithreading class
<?php
class download extends Thread {
public $i;
public $res;
public function __construct($s){
$this->i = $s;
}
public function run() {
try{
$url = "http://my.link.com/{$this->i}";
set_time_limit(0);
$id = md5(uniqid());
$tempName = md5($id.time());
$tmp = "downloads/{$tempName}";
$fp = fopen (dirname(__FILE__) . '/'.$tmp, 'w+');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
curl_close($ch);
fclose($fp);
require('scanner.php');
$results = scanfiles($tmp);
unlink($tmp);
$this->res = $results;
}catch(Exception $e){
$this->res = '0';
}}} ?>
Into fopen you're passing absolute path (dirname(__FILE__) . "/{$tmp}") while into unlink relative path, just use abslute everywhere and it should work. Btw you can use just __DIR__ instead dirname(__FILE__) since PHP 5.3.
Related
I wanted to save a file from External Url which would have any kind of file like say "jpg, png, mp4 etc"
I want to save it in the public directory of Laravel App. How could I do that? Any help will be highly appreciated.
I tried the following thing, but it's saving file in my storage folder:
Storage::put($name, $contents);
Thanks
create an img folder in public path and :
$image = file_get_contents("https://logos-download.com/wp-content/uploads/2016/09/Laravel_logo.png");
file_put_contents(public_path('img/a.png'), $image);
use File like below
use Illuminate\Support\Facades\File;
and then
File::put(public_path( 'ANY FILE YOU WANT' ));
example:
File::put( public_path( 'js/a.js'), ' CONTENT ');
Download files from external URL after authentication.
public function file_get_contents_curl( $url ) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
public function downloadFile( $imgName, $url, $path )
{
$data = $this->file_get_contents_curl( $url );
file_put_contents( $path.$imgName, $data );
echo "File downloaded!";
}
Code for creating a new folder based on the date.
public function imgBackupFolder( $currentShop ) {
$folderName = 'export'.DS.str_replace( '.', '_', $currentShop->shopify_domain ).DS.'images'.DS.date( 'Y_m_d' ).DS;
return $this->createFolder( $folderName );
}
/*
* Create folder based on the store,date,export type
*/
private function createFolder( $folderName ) {
try {
$path = public_path( $folderName );
if( !File::isDirectory( $path ) ){
File::makeDirectory( $path, 0777, true, true );
}
return $path;
} catch (Exception $ex) {
Log::error( $ex->getMessage() );
}
}
I just can get the temp file path,like D:\XAMPP\tmp\phpE185.tmp...But the $_FILE array is null,because I do a transport from a url to another url.So how to move this temp file?
here is my code:
class UserController extends Controller
{
public function getRank(){
echo "waht";
}
public function uploadTrans(Request $request){
$image = $request->image;
$name = $request->name;
$image = urlencode($image);
$curlPost = "name=$name&image=$image";
$uploadApi = "http://mdx.ittun.com/authprac/public/upload";
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$uploadApi);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$curlPost);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
}
public function upload (Request $request){
$fileTempName = $request->image;
print_r($fileTempName);
// here I just can get the temp file path..$_FILES array is null
}
}
PHP has a move_uploaded_file() function for this purpose.
Since you've tagged your question with laravel, see their docs regarding uploaded files:
$request->file('photo')->move($destinationPath);
I am trying to get song name / artist name / song length / bitrate etc from a remote .mp3 file such as http://shiro-desu.com/scr/11.mp3 .
I have tried getID3 script but from what i understand it doesn't work for remote files as i got this error: "Remote files are not supported - please copy the file locally first"
Also, this code:
<?php
$tag = id3_get_tag( "http://shiro-desu.com/scr/11.mp3" );
print_r($tag);
?>
did not work either.
"Fatal error: Call to undefined function id3_get_tag() in /home4/shiro/public_html/scr/index.php on line 2"
As you haven't mentioned your error I am considering a common error case undefined function
The error you get (undefined function) means the ID3 extension is not enabled in your PHP configuration:
If you dont have Id3 extension file .Just check here for installation info.
Firstly, I didn’t create this, I’ve just making it easy to understand with a full example.
You can read more of it here, but only because of archive.org.
https://web.archive.org/web/20160106095540/http://designaeon.com/2012/07/read-mp3-tags-without-downloading-it/
To begin, download this library from here: http://getid3.sourceforge.net/
When you open the zip folder, you’ll see ‘getid3’. Save that folder in to your working folder.
Next, create a folder called “temp” in that working folder that the following script is going to be running from.
Basically, what it does is download the first 64k of the file, and then read the metadata from the file.
I enjoy a simple example. I hope this helps.
<?php
require_once("getid3/getid3.php");
$url_media = "http://example.com/myfile.mp3"
$a=getfileinfo($url_media);
echo"<pre>";
echo $a['tags']['id3v2']['album'][0] . "\n";
echo $a['tags']['id3v2']['artist'][0] . "\n";
echo $a['tags']['id3v2']['title'][0] . "\n";
echo $a['tags']['id3v2']['year'][0] . "\n";
echo $a['tags']['id3v2']['year'][0] . "\n";
echo "\n-----------------\n";
//print_r($a['tags']['id3v2']['album']);
echo "-----------------\n";
//print_r($a);
echo"</pre>";
function getfileinfo($remoteFile)
{
$url=$remoteFile;
$uuid=uniqid("designaeon_", true);
$file="temp/".$uuid.".mp3";
$size=0;
$ch = curl_init($remoteFile);
//==============================Get Size==========================//
$contentLength = 'unknown';
$ch1 = curl_init($remoteFile);
curl_setopt($ch1, CURLOPT_NOBODY, true);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_HEADER, true);
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
$data = curl_exec($ch1);
curl_close($ch1);
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
$contentLength = (int)$matches[1];
$size=$contentLength;
}
//==============================Get Size==========================//
if (!$fp = fopen($file, "wb")) {
echo 'Error opening temp file for binary writing';
return false;
} else if (!$urlp = fopen($url, "r")) {
echo 'Error opening URL for reading';
return false;
}
try {
$to_get = 65536; // 64 KB
$chunk_size = 4096; // Haven't bothered to tune this, maybe other values would work better??
$got = 0; $data = null;
// Grab the first 64 KB of the file
while(!feof($urlp) && $got < $to_get) { $data = $data . fgets($urlp, $chunk_size); $got += $chunk_size; } fwrite($fp, $data); // Grab the last 64 KB of the file, if we know how big it is.
if ($size > 0) {
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RESUME_FROM, $size - $to_get);
curl_exec($ch);
}
// Now $fp should be the first and last 64KB of the file!!
#fclose($fp);
#fclose($urlp);
}
catch (Exception $e) {
#fclose($fp);
#fclose($urlp);
echo 'Error transfering file using fopen and cURL !!';
return false;
}
$getID3 = new getID3;
$filename=$file;
$ThisFileInfo = $getID3->analyze($filename);
getid3_lib::CopyTagsToComments($ThisFileInfo);
unlink($file);
return $ThisFileInfo;
}
?>
What I want to do is, to switch from FTP deployment into GIT. I mean, I want to keep automatically keep synced my Bitbucket private repo and my shared webhosting. I googled and found following script to deploy my webserver (based on this article).
// Set these dependant on your BB credentials
$username = 'username';
$password = 'password';
// Grab the data from BB's POST service and decode
$json = stripslashes($_POST['payload']);
$data = json_decode($json);
// Set some parameters to fetch the correct files
$uri = $data->repository->absolute_url;
$node = $data->commits[0]->node;
$files = $data->commits[0]->files;
// Foreach through the files and curl them over
foreach ($files as $file) {
if ($file->type == "removed") {
unlink($file->file);
} else {
$url = "https://api.bitbucket.org/1.0/repositories"
. $uri . "raw/" .$node ."/" . $file->file;
$path = $file->file;
$dirname = dirname($path);
if (!is_dir($dirname)) {
mkdir($dirname, 0775, true);
}
$fp = fopen($path, 'w');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
$data = curl_exec($ch);
curl_close($ch);
fclose($fp);
}
}
The problem is, this works on simple changesets like 5-10 file change. But when I push the whole project for the first time (for example with 600-700 files and folders) into my bitbucket private profile, this script doesn't work. (just doesn't, no error on errors.log)
What am I missing?
By the way, Can I do something like that:
As we know, Bitbucket can send POST information into an exact url (given by user) directly after a commit has been made. So when deploy.php receives POST, we can get the entire commit as a zip or tar, clean our current files and unzip the new commit into webserver.
Is that possible? If yes then how? Any other good way?
Update
I found the code below for automated deploying php project. The problem is https://bitbucket.org/$username/$reponame/get/tip.zip this url doesnt work on bitbucket private git repo: probably related with authentication (I haven't tested this on public repo) What i need is to get the last commit's zip file and unzip inside my project.
<?
// your Bitbucket username
$username = "edifreak";
// your Bitbucket repo name
$reponame = "canvas-game-demo";
// extract to
$dest = "./"; // leave ./ for relative destination
////////////////////////////////////////////////////////
// Let's get stuff done!
// set higher script timeout (for large repo's or slow servers)
set_time_limit(380);
// download the repo zip file
$repofile = file_get_contents("https://bitbucket.org/$username/$reponame/get/tip.zip");
file_put_contents('tip.zip', $repofile);
unset($repofile);
// unzip
$zip = new ZipArchive;
$res = $zip->open('tip.zip');
if ($res === TRUE) {
$zip->extractTo('./');
$zip->close();
} else {
die('ZIP not supported on this server!');
}
// delete unnecessary .hg files
#unlink("$username-$reponame-tip/.hgignore");
#unlink("$username-$reponame-tip/.hg_archival.txt");
// function to delete all files in a directory recursively
function rmdir_recursively($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir."/".$object) == "dir") rmdir_recursively($dir."/".$object); else unlink($dir."/".$object);
}
}
reset($objects);
rmdir($dir);
}
}
// function to recursively copy the files
function copy_recursively($src, $dest) {
if (is_dir($src)) {
if($dest != "./") rmdir_recursively($dest);
#mkdir($dest);
$files = scandir($src);
foreach ($files as $file)
if ($file != "." && $file != "..") copy_recursively("$src/$file", "$dest/$file");
}
else if (file_exists($src)) copy($src, $dest);
rmdir_recursively($src);
}
// start copying the files from extracted repo and delete the old directory recursively
copy_recursively("$username-$reponame-tip", $dest);
// delete the repo zip file
unlink("tip.zip");
// Yep, we're done :)
echo "We're done!";
?>
This solution do not provides authentication:
// download the repo zip file
$repofile = file_get_contents("https://bitbucket.org/$username/$reponame/get/tip.zip");
file_put_contents('tip.zip', $repofile);
unset($repofile);
But curl allows it. So a zip archive can be downloaded from a private repository in same way like in first script.
$node = ''; // a node from repo, like c366e96f16...
$fp = fopen($path, 'w');
$ch = curl_init("https://bitbucket.org/$username/$reponame/get/$node.zip");
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
$data = curl_exec($ch);
curl_close($ch);
fclose($fp);
I have tested it for my bitbucket account. It's work very well.
If necessary to get last changeset node that we should use bitbucket api GET a list of changesets:
$username = 'login';
$password = 'pass';
$owner = $username; // if user is owner
$repo = 'repo name';
$response = "";
$callback = function($url, $chunk) use (&$response){
$response .= $chunk;
return strlen($chunk);
};
$ch = curl_init("https://api.bitbucket.org/1.0/repositories/$owner/$repo/changesets?limit=1");
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent:Mozilla/5.0'));
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
curl_exec($ch);
curl_close($ch);
$changesets = json_decode($response, true);
$node = $changesets['changesets'][0]['node'];
$raw_node = $changesets['changesets'][0]['raw_node'];
print($node . PHP_EOL);
print($raw_node . PHP_EOL);
I recently discovered Capistrano which is a great tool. It was initially developed for ruby but it's also great in combination with php http://www.davegardner.me.uk/blog/2012/02/13/php-deployment-with-capistrano/
Based on your update, replace you php files contents with code below:
<?php
// Set these dependant on your BB credentials
$username = '';
$password = '';
// your Bitbucket repo name
$reponame = "";
// extract to
$dest = "./"; // leave ./ for relative destination
// Grab the data from BB's POST service and decode
$json = stripslashes($_POST['payload']);
$data = json_decode($json);
// set higher script timeout (for large repo's or slow servers)
set_time_limit(5000);
// Set some parameters to fetch the correct files
$uri = $data->repository->absolute_url;
$node = $data->commits[0]->node;
$files = $data->commits[0]->files;
// download the repo zip file
$fp = fopen("tip.zip", 'w');
$ch = curl_init("https://bitbucket.org/$username/$reponame/get/$node.zip");
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
$data = curl_exec($ch);
curl_close($ch);
fclose($fp);
// unzip
$zip = new ZipArchive;
$res = $zip->open('tip.zip');
if ($res === TRUE) {
$zip->extractTo('./');
$zip->close();
} else {
die('ZIP not supported on this server!');
}
// function to delete all files in a directory recursively
function rmdir_recursively($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir . "/" . $object) == "dir")
rmdir_recursively($dir . "/" . $object); else
unlink($dir . "/" . $object);
}
}
reset($objects);
rmdir($dir);
}
}
// function to recursively copy the files
function copy_recursively($src, $dest) {
if (is_dir($src)) {
if ($dest != "./")
rmdir_recursively($dest);
#mkdir($dest);
$files = scandir($src);
foreach ($files as $file)
if ($file != "." && $file != "..")
copy_recursively("$src/$file", "$dest/$file");
}
else if (file_exists($src))
copy($src, $dest);
rmdir_recursively($src);
}
// start copying the files from extracted repo and delete the old directory recursively
copy_recursively("$username-$reponame-$node", $dest);
// delete the repo zip file
unlink("tip.zip");
?>
Update
Here are repositories of this script (Modified by Me) on
GitHub
Bitbucket
My Class for download file direct from a link:
MyClass{
function download($link){
......
$ch = curl_init($link);
curl_setopt($ch, CURLOPT_FILE, $File->handle);
curl_setopt($ch,CURLOPT_WRITEFUNCTION , array($this,'__writeFunction'));
curl_exec($ch);
curl_close($ch);
$File->close();
......
}
function __writeFunction($curl, $data) {
return strlen($data);
}
}
I want know how to use CRULOPT_WRITEFUNCTION when download file.
Above code if i remove line:
curl_setopt($ch,CURLOPT_WRITEFUNCTION , array($this,'__writeFunction'));
Then it will run good, i can download that file.But if i use CURL_WRITEFUNCTION option i can't download file.
I know this is an old question, but maybe my answer will be of some help for you or someone else. Try this:
function get_write_function(){
return function($curl, $data){
return strlen($data);
}
}
I don't know exactly what you want to do, but with PHP 5.3, you can do a lot with the callback. What's really great about generating a function in this way is that the values passed through the 'use' keyword remain with the function afterward, kind of like constants.
function get_write_function($var){
$obj = $this;//access variables or functions within your class with the object variable
return function($curl, $data) use ($var, $obj) {
$len = strlen($data);
//just an example - you can come up with something better than this:
if ($len > $var){
return -1;//abort the download
} else {
$obj->do_something();//call a class function
return $len;
}
}
}
You can retrieve the function as a variable as follows:
function download($link){
......
$var = 5000;
$write_function = $this->get_write_function($var);
$ch = curl_init($link);
curl_setopt($ch, CURLOPT_FILE, $File->handle);
curl_setopt($ch, CURLOPT_WRITEFUNCTION , $write_function);
curl_exec($ch);
curl_close($ch);
$File->close();
......
}
That was just an example. You can see how I used it here: Parallel cURL Request with WRITEFUNCTION Callback. I didn't actually test all of this code, so there may be minor errors. Let me know if you have problems, and I'll fix it.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_BUFFERSIZE, 8096);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, 'http://blog.ronnyristau.de/wp-content/uploads/2008/12/php.jpg');
$content = curl_exec($ch);
curl_close($ch);
$out = fopen('/tmp/out.png','w');
if($out){
fwrite($out, $content);
fclose($out);
}
Why do you use curl to download a file? Is there a special reason? You can simply use fopen and fread
I have written a small class for it.
<?php
class Utils_FileDownload {
private $source;
private $dest;
private $buffer;
private $overwrite;
public function __construct($source,$dest,$buffer=4096,$overwrite=false){
$this->source = $source;
$this->dest = $dest;
$this->buffer = $buffer;
$this->overwrite = $overwrite;
}
public function download(){
if($this->overwrite||!file_exists($this->dest)){
if(!is_dir(dirname($this->dest))){mkdir(dirname($this->dest),0755,true);}
if($this->source==""){
$resource = false;
Utils_Logging_Logger::getLogger()->log("source must not be empty.",Utils_Logging_Logger::TYPE_ERROR);
}
else{ $resource = fopen($this->source,"rb"); }
if($this->source==""){
$dest = false;
Utils_Logging_Logger::getLogger()->log("destination must not be empty.",Utils_Logging_Logger::TYPE_ERROR);
}
else{ $dest = fopen($this->dest,"wb"); }
if($resource!==false&&$dest!==false){
while(!feof($resource)){
$read = fread($resource,$this->buffer);
fwrite($dest,$read,$this->buffer);
}
chmod($this->dest,0644);
fclose($dest); fclose($resource);
return true;
}else{
return false;
}
}else{
return false;
}
}
}
It seems like cURL uses your function instead of writing to the request once CURLOPT_WRITEFUNCTION is specified.
So the correct solution would be :
MyClass{
function download($link){
......
$ch = curl_init($link);
curl_setopt($ch, CURLOPT_FILE, $File->handle);
curl_setopt($ch,CURLOPT_WRITEFUNCTION , array($this,'__writeFunction'));
curl_exec($ch);
curl_close($ch);
$File->close();
......
}
function __writeFunction($curl, $data) {
echo $data;
return strlen($data);
}
}
This can also handle binary files as well.