I am executing the following commands:
<?php
copy ("http://localhost/.../DSCF8253.JPG" , "sites/default/files/DSCF8253.JPG"); // Success!
copy ("http://localhost/.../DSCF8260.JPG" , "sites/default/files/DSCF8260.JPG"); // Success!
copy ("http://localhost/.../HERMAN 085.jpg" , "sites/default/files/HERMAN 085.jpg" ); // Fail!
?>
The first two copy fine, but not the last one. Why?
It must have something to do with the filenames (the last one has a SPACE before the 085).
Any help would be greatly appreciated!
http://localhost/.../HERMAN 085.jpg
Should be
http://localhost/.../HERMAN%20085.jpg
Copy & the http wrappers are less forgiving then browsers / user-agents when it comes to invalid urls. A space in an url is invalid, so it should be urlencode'd.
//i used this code once i tried to copy images to a wordpress site and set post featured image
//i only mentioned the part you want and did not mention other parts
$image_url = 'http://example.com/images/my image with spaces.jpg';
try {
//throw exception if can't move the file
if (!copy(str_replace(" ","%20",$image_url),$file)) {
$errors = error_get_last();
throw new Exception('Could not copy file');
}
} catch (Exception $e) {
echo $e->getMessage();
}
//using urlencode will corrupt the url if used with the full url
//it will generate something like http%dsf%swdfablablabla
//if you need to encode you will encode anything after http://yoursite.com/{encode only works here}
Strangest thing: the %20 way doesn't seem to do the trick, but after some trying
in vain (first with %20, then quoting the filename, then double-quoting, then
protecting spaces, tell me if I missed something), now the original version works flawlessly. This is Windows 10, PHP 5.5.12 and we are in year 2016.
Good luck with all these deterministic, finite-state systems :)
A possible solution btw, is to use exec() and do a copy on the operating
system level. Then again, it's OS specific.
Related
This question is asked before but non of the answers worked for me.
I use the following code to directly copy a file from a remote server to my server,
<?php
set_time_limit(0); //Unlimited max execution time
$remote_file_url = $_GET['url'];
$ext = pathinfo($remote_file_url, PATHINFO_EXTENSION);
$name = basename($remote_file_url);
if(isset($ext)){
$local_file = 'download/'.$name.'.'.$ext;
}
else
$local_file = 'download/'.$name;
$copy = copy( $remote_file_url, "1.mp4" );
if( !$copy ) {
echo "Doh! failed to copy $file...\n";
}
else{
echo "WOOT! success to copy $file...\n";
}
?>
It works well but it doesn't copy the files I get from Youtube. I use 1-Click Youtube Video Downloader extension for Firefox which gives me direct link to youtube videos. I can use these direct links in browser and Internet Download Manager as well.
For example the direct url of
https://www.youtube.com/watch?v=xPXrJwQ5lqQ
is
https://r6---sn-ab5l6nzy.googlevideo.com/videoplayback?ipbits=0&requiressl=yes&sparams=dur,ei,expire,id,initcwndbps,ip,ipbits,ipbypass,itag,lmt,mime,mip,mm,mn,ms,mv,pl,ratebypass,requiressl,source&ei=3DNOWfq4CImGc9rxvcgO&signature=3D188D073D872381433A45462E84928383D10D02.4E0AF7D777E76AA19A576D42983A81F4E62EF84D&lmt=1472135086539955&mime=video%2Fmp4&ratebypass=yes&id=o-ABaoUEn3pBt5SLXdWXlrzCdteMLfLPizrRTPoakDoLSX&expire=1498318908&source=youtube&dur=119.211&itag=22&pl=20&ip=162.217.31.128&key=cms1&redirect_counter=1&req_id=ce038b9993a9a3ee&cms_redirect=yes&ipbypass=yes&mip=159.203.89.210&mm=31&mn=sn-ab5l6nzy&ms=au&mt=1498297234&mv=m
The problem is my code can't copy this file to my server. I would like to know of there is any way to resolve such urls?
The error is
failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden in /home/...
thanks in advance.
Well, I have no idea why that happened. (Would it be expired?I hope not) I just managed to try another link for the above video (copy the link using right click) in your code as the $remote_file_url and it worked as expected
How did I get that link?
I've used the underlined library : YouTube-Downloader to the 1-Click Youtube Video Downloader extension (it is inherently used by that extension ) this way you will have more control over the process. Then after hosting the files in your web server. Simply run the index.php and when you use it, you'll get something like :
Then you can automate this last part to suit your needs.
That doesn't mean that all videos could be smoothly downloaded with this method. Because of the used videos that have signatures issue or that are recently uploaded issue and here's the list of issues of Youtube-Downloader
For that There is a fix that is somewhat involved: youtube-dl-php, it is based on a sound principle : there is a very good command line utility to download YouTube videos called youtube-dl : here is the download page
Basically, you'll just call it using php. Then, notice that you'll need its path installed in order for the following to work
After you install Composer, go to your web project folder
and run composer require norkunas/youtube-dl-php as explained in the Github page
When running its example, I've get an error
proc_open() 267 CreateProcess failed
I've never dealt with Symphony before and I've found it particularly interesting to play with YoutubeDl.php and redefine the $arguments passed to createProcess and commenting out much of the less useful configuration options to get rid of that error, give it more time to run with
ini_set('max_execution_time', 300);
And yikes it was downloaded.
You don't have to follow this unless you couldn't figure out a better way. It is just supposed to give you an idea of where lies the problem if you havn'et figure it out. And if you have that problem in the first place.
private function createProcess(array $arguments = [])
{
array_unshift($arguments, $this->binPath ?: 'youtube-dl');
$process = new Process("youtube-dl https://www.youtube.com/watch?v=nDMwW41AlSI");
/*$process->setEnv(['LANG' => 'en_US.UTF-8']);
$process->setTimeout($this->timeout);
$process->setOptions($this->processOptions);
if ($this->moveWithPhp) {
$cwd = sys_get_temp_dir();
} else {
$cwd = $this->downloadPath ?: sys_get_temp_dir();
}
$process->setWorkingDirectory($cwd);*/
return $process;
}
Or you can just write your own code that calls youtube-dl, good luck!
I simply cant wrap my head around why this simple code won't work on my local wamp server where i have other sites running.
<?php
$file = file_get_contents('C:\Users\Computer\input.txt', true);
echo $file;
?>
The file is where it should be.
I get the following error:
Warning: file_get_contents(C:\Users\Computer\input.txt): failed to open stream: No such file or directory in C:\Users\Computer\Dropbox\htdocs\ny\www\php\day2\code.php on line 3
But the file is exactly where it should be.
The file has all possible permissions to true (read, write ect.) in windows except for "special permissions".
What is not working correctly?
Regards,
Patrick
The solution was the extension. It was not correctly parsed. This was checked by using #VolkerK suggesting to check
Does the output of var_export(glob('C:\Users\Computer*')); contain
input.txt? Or is it false/null?
Thanks to #VolkerK for the help solving the problem.
Since I incorrectly said that it might be because of backslash escaping, I guess I need to redeem by saying something useful :)
So try:
$file = 'C:\Users\Computer\input.txt';
if(is_file($file))
{
$string = file_get_contents($file);
}
else
{
die("Uh oh! Seems like $file has got problems!");
}
Also, you are passing the second argument as true for searching the include path. Since your filepath is absolute, I suspect if you need this argument to be passed at all.
I am beginner to php and learning my ways around it. I know functions but nothing working out for me, making too many mistakes. If someone please help. Below is the part of the code of Image uploading function, I need to add function so that it renames the file by replacing spaces with hyphen (-) [after / while uploading of image file)
if(isset($input['pic'])){
if(isset($input['img_url']) && $input['img_url'] != ''){
input['pic_url'] = ImageHandler::uploadImage($input['img_url'], 'images', Helper::slugify($input['title']), 'url');
} else if(isset($input['pic_url'])){
$input['pic_url'] = ImageHandler::uploadImage(Input::file('pic_url'), 'images');
$input['pic'] = 1;
}
Thanks
EB
First of all use:
if (!empty($input['img_url'])) { ... }
instead of..
if (isset($input['img_url']) && $input['img_url'] != '') { ... }
As second please make sure before posting a question, if you posted all information what is necessary to answer your question. For example, in your code you're using ImageHandler::uploadImage() it's not clear what this class it's function does. Altho I can guess what the parameters are. Something like..?
ImageHandler::uploadImage($file, $folder, $name, $type);
Anyway I'm not sure, but if I'm right than try to modify the thrid parameter $name to your needs.
Not bad to mention, but this happens after the file has been uploaded to the temporary directory on the server after completion it will be moved to the selected directory with the choosen filename.
echo str_replace(" ", "-", end(explode("/", $image_path)));
My environment is: Windows, MsSQL and PHP 5.4.
My scenario:
I'm doing a small shell script that creates a full backup from my wanted database to a temp folder and then moves it to a new location.
The backup goes fine and the file is created to my temp folder. Then I rename it to the 2nd folder and sometimes it goes ok, sometimes it cannot find the source file.
Of course at this point I know that I could skip the temporary location alltogether, but the actual problem with not finding the file bothers me. Why is it so random and might it also affect other file functions I've written before this one... Also i need to be able to control how and when the files move to the destination.
The base code is simple as it should be (although this is a simplified version of my actual code, since I doubt anyone would be interested in my error handling/logging conditions):
$query = "use test; backup database test to disk '//server01/temp/backups/file.bak', COMPRESSION;";
if($SQLClass->query($query)) {
$source="////server01//temp//backups//file.bak";
$destination="////server02//storage//backups//file.bak";
if(!rename($source , $destination)) {
//handleError is just a class function of mine that logs and outputs errors.
$this->handleError("Moving {$source} to {$destination} failed.");
}
}
else {
die('backup failed');
}
What I have tried is:
I added a file_exists before it and it can't find the source file either, when rename can't.
As the file can't be found, copy() and unlink() will not work either
Tried clearstatcache()
Tried sleep(10) after the sql backup completes
None of these didn't help at all. I and google seem to be out of ideas on what to do or try next. Of course I could some shell_execing, but that wouldn't remove my worries about my earlier products.
I only noticed this problem when I tried to run the command multiple times in a row. Is there some sort of cache for filenames that clearstatcache() won't touch ? It seems to be related to some sort of ghost file phenomena, where php is late to refresh the file system contents or such.
I would appreciate any ideas on what to try next and if you read this far thank you :).
You may try calling system's copy command.
I had once problem like yours (on Linux box) when i had to copy files between two NFS shares. It just failed from time to time with no visible reasons. After i switched to cp (analog of Windows copy) problem has gone.
Surely it is not perfect, but it worked for me.
It might be cache-related, or the mysql process has not yet released the file.
mysql will dump the file into another temp file, first and finally moves it to your temp folder.
While the file is beeing moved, it might be inaccessible by other processes.
First I would try to glob() all the files inside temp dir, when the error appears. Maybe you notice, its still not finished.
Also have you tried to implemente something like 10 retry iterations, with some delay?
$notMoved = 0;
while($notMoved < 10){
$source="////server01//temp//backups//file.bak";
$destination="////server02//storage//backups//file.bak";
if(!rename($source , $destination)) {
//handleError is just a class function of mine that logs and outputs errors.
if ($notMoved++ < 10){
sleep(20);
} else {
$this->handleError("Moving {$source} to {$destination} failed.");
break;
}
}else{
break;
}
}
To bypass the issue:
Don't dump and move
Move then dump :-)
(ofc. your backup store would be one behind then)
$source="////server01//temp//backups//file.bak";
$destination="////server02//storage//backups//file.bak";
if(!rename($source , $destination)) {
//handleError is just a class function of mine that logs and outputs errors.
$this->handleError("Moving {$source} to {$destination} failed.");
}
$query = "use test; backup database test to disk '//server01/temp/backups/file.bak', COMPRESSION;";
if($SQLClass->query($query)) {
//done :-)
}
else {
die('backup failed');
}
Try
$source = "\\server01\temp\backups\file.bak";
$destination = "\\server02\storage\backups\file.bak";
$content = file_get_content($source);
file_put_contents($destination, $content);
I'm having an extremely weird problem with a PHP script of mine.
I'm uploading a couple of files and having PHP put them all in one folder.
I've have trouble with random files being sent and random ones not being sent. So I debugged it and I got a very weird result from the $_FILES[] array.
I tried it with 3 files.
$_FILES["addFile"]["name"] Holds the names of the 3 files.
You'd expect $_FILES["addFile"]["tmp_name"] to hold the 3 temporary names that PHP uses to copy the files, but it doesn't. It holds just one name. The other 2 are empty strings, which generate an error whilst uploading(which I supress from being displayed)
This is very odd. I've tried mulitple situations and it just keeps on happening.
This must be something in my settings or perhaps even my code.
Here's my code:
$i = 0;
if (!empty($_FILES['addFile'])) {
foreach($_FILES['addFile'] as $addFile) {
$fileToCopy = $_FILES["addFile"]["tmp_name"][$i];
$fileName = $_FILES["addFile"]["name"][$i];
$i++;
if(!empty($fileToCopy)){
$copyTo = $baseDir."/".$fileName;
#copy($fileToCopy, $copyTo) or die("cannot copy ".$fileToCopy." to ".$copyTo);
}
}
exit(0);
}
Since the tmp_name is empty, the if-value will be false so it's gonna skip the die() function.
Does anybody know what might be causing this?
further info: I'm using Windows XP, running WAMP server. Never had this problem before and I can acces all maps from which I've tried to upload. Security settings of windows can't be the issue I think.
I'm sorry but it seams to me that you are trying to upload all 3 files with the same variable name? Is this right?
But this will not work because they will overwrite each other.
I think the better an cleaner way it would be to use something like
$i = 0;
foreach($_FILES['addFile'.$i] as $addFile) {
if(!empty($addFiles) {
move_uploaded_file($addFile['temp_name'], 'YOUR DIRECTORY');
}
$i++;
}
Relevent, but probably not going to help: but move_uploaded_file is a (slightly) better way to handle uploaded files than copy.
Are any of the files large? PHP has limits on the filesize and the time it can take to upload them ...
Better to send you here than attempt to write up what it says:
http://uk3.php.net/manual/en/features.file-upload.common-pitfalls.php
Your loop logic is incorrect. You are using a foreach loop on the file input name directly, which stores several properties that are of no interest to you ('type','size', etc).
You should get the file count from the first file and use it as the loop length:
if (!empty($_FILES['addFile']) && is_array($_FILES['addFile']['name'])) {
$length = count($_FILES['addFile']['name']);
for($i = 0; $i < $length; $i++) {
$result = move_uploaded_file($_FILES['addFile']['tmp_name'][$i],$baseDir."/" . $_FILES['addFile']['name'][$i]);
if($result === false) {
echo 'File upload failed. The following error has occurred: ' . $_FILES['addFile']['error'][$i];
}
}
}
Check the error code if you are still having problems, it should provide all the information you need to debug it.