12

I've been looking all over the place for the last two days and trying everything and still can't get anything to work. I feel like this should be a relatively simple thing to do.

All I want to do is download a remote file from a URL to a directory on my server.

So, for example, if

$_url = http://www.freewarelovers.com/android/download/temp/1306495040_Number_Blink_1.1.1.apk

and $_dir = /www/downloads/

Then when all is said and done I want 1306495040_Number_Blink_1.1.1.apk in /www/downloads/

I've tried the copy() function, I've tried

file_put_contents("$_dir.$_file_name", file_get_contents($_url));

and get the following error:

file_get_contents(): failed to open stream: HTTP request failed!

Corey
  • 771
  • 3
  • 14
  • 32
  • 1
    what about if you tell us which are the errors? – dynamic Jun 14 '11 at 19:02
  • It isn't giving me any errors that's the problem.. And I feel like the question is already very clear without the additional detail I put. I really didn't even need to tell you what I already tried I just want a solution – Corey Jun 14 '11 at 19:03
  • What errors are you getting with `file_get_contents`? Also, if you have access to the `curl` module, you can try that too. – Rob Jun 14 '11 at 19:04
  • I have `error_reporting(E_ALL);` and `display_errors = On` – Corey Jun 14 '11 at 19:05
  • it's impossible that it doenst' work and it doenst' give any errors – dynamic Jun 14 '11 at 19:09
  • I'm getting `file_get_contents(): failed to open stream: HTTP request failed!` – Corey Jun 14 '11 at 19:17
  • 2
    doh! you said there were no errors. -1 – dynamic Jun 14 '11 at 19:45
  • This is a new error. I've been trying new things since posting this. You are the least helpful person I've ever seen on stackoverflow – Corey Jun 14 '11 at 19:54
  • What did you change that started causing the error? You're not exactly being the most helpful question asker ever, yourself. – ceejayoz Jun 14 '11 at 19:58
  • Does it really matter what I changed? I keep changing and trying new things, I am not going to post every little change I try that doesn't work. You know I am trying to use `file_get_contents():` and you know the error I'm getting. I think that should be enough to work with assuming you know PHP. I don't, which is why I'm here. – Corey Jun 14 '11 at 20:02
  • 3
    If you don't know PHP then how can you assume what details are and are not relevant? – Andrew Jun 14 '11 at 20:06
  • I just don't know what that error means. Someone familiar with HTML and PHP most likely would. I've never seen so many condescending people in one place before – Corey Jun 14 '11 at 20:10
  • 1
    "Does it really matter what I changed?" YES! If you change something and it starts acting differently, that's **hugely** important info to have for troubleshooting purposes. – ceejayoz Jun 14 '11 at 20:13
  • All I changed was `$_dir.$_file_name`. The same thing I changed in my post. Still not sure how that helps you tell me what `failed to open stream: HTTP request failed!` means – Corey Jun 14 '11 at 20:16
  • I am not acting arrogant you guys just aren't helping and it's frustrating. You are spending a lot of time pointing out irrelevant mistakes I made in my question and not a lot of time actually trying to help. I still have no idea what `failed to open stream: HTTP request failed!` means. If you weren't so condescending I would not have been so "arrogant" – Corey Jun 14 '11 at 20:33
  • All I needed was this line to get rid of the error `ini_set ('user_agent', $_SERVER['HTTP_USER_AGENT']);` Thanks for all the "help" – Corey Jun 14 '11 at 20:42
  • 1
    @yes123, once again, try to [be nice](http://stackoverflow.com/faq#benice). Thanks! – Michael Myers Jun 14 '11 at 21:50
  • 1
    @Corey How, exactly, could we be expected to solve a problem in code we never saw? – ceejayoz Jun 15 '11 at 13:20

8 Answers8

22

This should do it :

set_time_limit(0);

$url = 'http://www.freewarelovers.com/android/download/temp/1306495040_Number_Blink_1.1.1.apk';
$file = fopen(dirname(__FILE__) . '/downloads/a.apk', 'w+');

$curl = curl_init();

// Update as of PHP 5.4 array() can be written []
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
//  CURLOPT_BINARYTRANSFER => 1, --- No effect from PHP 5.1.3
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_FILE           => $file,
    CURLOPT_TIMEOUT        => 50,
    CURLOPT_USERAGENT      => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'
]);

$response = curl_exec($curl);

if($response === false) {
    // Update as of PHP 5.3 use of Namespaces Exception() becomes \Exception()
    throw new \Exception('Curl error: ' . curl_error($curl));
}

$response; // Do something with the response.
Sparkup
  • 3,686
  • 2
  • 36
  • 50
  • 1
    Thank you, this is the first helpful comment I've gotten. Unfortunately I'm still having the same problem. It doesn't look like I'm getting the whole file (only about 4 KB out of the 139 KB). And there are no errors in the `error.log`. – Corey Jun 14 '11 at 19:33
  • I don't think it's that. Timeout is set for 60 seconds and the entire page is opening way faster than that. Any other idea what is could be? – Corey Jun 14 '11 at 19:37
  • add this : `set_time_limit(0); ini_set('display_errors',true);` at the beginning – Sparkup Jun 14 '11 at 19:46
  • Nope. Still no errors and it is actually 0 B not 4 KB. I was accidentally looking at the size of the directory. So the file isn't downloading at all and I still don't see any errors. – Corey Jun 14 '11 at 19:53
  • I really appreciate all the help; unfortunately I still can't get it working with the link I'm trying. I'm just curious, have you gotten it to work with this link `http://www.freewarelovers.com/android/download/temp/1306495040_Number_Blink_1.1.1.apk` – Corey Jun 15 '11 at 02:16
  • It now looks like I'm only getting 20KB – Corey Jun 15 '11 at 02:18
  • 1
    Since you added an update for PHP5.4, I figure you could remove the `CURLOPT_BINARYTRANSFER` line as it has no effect. `From PHP 5.1.3, this option has no effect: the raw output will always be returned when CURLOPT_RETURNTRANSFER is used.` [http://php.net/manual/en/function.curl-setopt.php](http://php.net/manual/en/function.curl-setopt.php) – duckboy81 Dec 26 '16 at 23:45
  • 1
    If you do `curl_init($url)` then you don't need to also set `CURLOPT_URL`. Or if you prefer to set it in the option array, then you can just do `curl_init()` instead. It's not necessary to do both. – jlh Sep 06 '18 at 12:02
  • Thank you, i proccess files with success. – ElvisP Mar 30 '20 at 17:04
17
$url  = 'http://www.example.com/a-large-file.zip';
$path = '/path/to/a-large-file.zip';

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$data = curl_exec($ch);

curl_close($ch);

file_put_contents($path, $data);

it uses curl

$url is the file url

$path is where and the name to save the file

i hope it works

7

Since PHP 5.1.0, file_put_contents() supports writing piece-by-piece by passing a stream-handle as the $data parameter:
No need to use Curl

file_put_contents("Tmpfile.zip", fopen("http://someurl/file.zip", 'r'));
Kuldeep
  • 202
  • 3
  • 8
5

Use curl to download file from remote server like below.

$url = "http://path/toserver/filename";
$destination = "uploads/filename";    
$fp = fopen ($destination, 'w+');
  $ch = curl_init();
  curl_setopt( $ch, CURLOPT_URL, $url );
  curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true );
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, false );
  curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );

  curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
  curl_setopt( $ch, CURLOPT_FILE, $fp );
  curl_exec( $ch );
  curl_close( $ch );
  fclose( $fp );

reference http://www.tricksofit.com/2014/04/download-file-from-remote-server-in-php

Harish Singh
  • 3,359
  • 5
  • 24
  • 39
4

file_put_contents expects a filename, not a directory name.

elitalon
  • 9,191
  • 10
  • 50
  • 86
ceejayoz
  • 176,543
  • 40
  • 303
  • 368
  • 1
    he pass $_url to get_contents. What are you talking about – dynamic Jun 14 '11 at 19:04
  • 1
    Probably a typo. OP is definitely passing just a directory to file_put_contents, which is probably where things are blowing up. – Marc B Jun 14 '11 at 19:05
  • 1
    i think he means `file_put_contents` – Karolis Jun 14 '11 at 19:05
  • Thanks @Marc B, typo on my part. – ceejayoz Jun 14 '11 at 19:06
  • @ceey: you wrote `*_get_*()` before ;) – dynamic Jun 14 '11 at 19:07
  • I do have a file name. `$_dir.$file_name` is a full path to the file name. `$file_name` is the name of the file which I already extracted from the URL – Corey Jun 14 '11 at 19:20
  • 1
    @Corey Nice of you to include that code in the original question. *sigh* – ceejayoz Jun 14 '11 at 19:51
  • It was there, I just wasn't clear on what my variables were in the original post. – Corey Jun 14 '11 at 19:55
  • It may have been in the code, but it certainly wasn't in the question (http://stackoverflow.com/revisions/6348602/1), hence this answer. We can't read your mind. – ceejayoz Jun 14 '11 at 19:57
  • Yes I understand that. What I don't understand is why you're getting so caught up on pointing out minor details. Especially when they don't help me solve my problem. If you don't want to help, fine. But you're wasting my time and yours pointing out irrelevant information – Corey Jun 14 '11 at 20:03
  • 1
    If your code was actually as originally written, it wouldn't have been a "minor detail", hence the posted answer. – ceejayoz Jun 14 '11 at 20:12
1

Split it into different stages:

$raw = file_get_contents($_url);
... check if $raw has anything useful in it
file_put_contents($_dir, $raw);
... check if the file showed up

Either the fetch is failing in file_get_contents, or the write is failing in file_put_contents, or the file you're downloading is too large and exceeds your PHP's default memory_limit.

Marc B
  • 356,200
  • 43
  • 426
  • 500
  • 1
    At the time I wrote it, there was no extra information. If you're going to be spamming downvotes, at least check that the "wrong" answer comes AFTER the latest change in the question. – Marc B Jun 14 '11 at 19:43
  • No, but it helps with diagnosis. Doing it all on one line just give you "x failed on line Y". – Marc B Jun 14 '11 at 20:27
  • that's enough in this case :) `failed to open stream: HTTP request failed!` anyway i would toggle off my -1 after your comments but 40min were passed already – dynamic Jun 14 '11 at 20:28
0

With validations...

Validate if file exists first:

function doesUrlExists($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if($code == 200){
        $status = true;
    }else{
        $status = false;
    }
    curl_close($ch);
    return $status;
}

And then put file content (with laravel storage class):

 if(!doesUrlExists($url_file)) {
     die('The remote file is not accessible. Please check the URL.');
 }

 Storage::disk('local')
          ->put($file_destintation, fopen($url_file, 'r'));
JuliSmz
  • 996
  • 1
  • 12
  • 26
0

You may not have fopen wrappers enabled so file_get_contents may not work. Try using curl or a library like Snoopy.

Nev Stokes
  • 9,051
  • 5
  • 42
  • 44