I have a script on my server to create a text file of a selected list of entries in my website database. I'd like to add an extension to that PHP script to automatically download the text file to a specific folder on a local PC (Windows 10).
Can anyone offer any suggestions on this please?

    You can go the other way around - create a script on the local PC to check the file location and download from there if it exists. However, you can't force a download to a computer from the web; you can ask the user if they want to download it, but just pushing the file down no matter what has all sorts of nasty implications.

      Thanks for your response. The problem is that I want to extract records from a secure database on the web-server and write them to a text file, but I don't want to leave the txt file on the server.
      I don't know how to connect and download selections from the database on the server using PHP on my local machine. Is that possible? (I am fairly new to PHP and PDO!)

        You can write a php script on the server that will gather and output the information from the database. On your local PC, write another script that calls to the script on the server (either a cURL call or direct link to the server script URL) and collects the information; that way you can skip writing a text file entirely. This is obviously a high-level description of the process, but it should give you a direction to start looking.

        Yes, I have created the txt file on the server using PHP/PDO - all in my local development environment of course. I know that in a live situation I could then download it by activating a local script or, even, by just using my FTP client.
        However, what I really wanted to do was either write the txt file directly to my local PC or automatically transfer it from the server when written. I don't want the txt file left on the server for more than a second or two (sensitive data).
        Maybe I'm looking for the impossible.
        Really appreciate you trying to help, thanks!

          It's generally a security thing where you don't allow servers to push something to your PC without you explicitly saying it's okay to do so. I.e., it's usually better to "pull" than to allow someone else to "push". But if you really want to allow the push, I suppose you could set up a SFTP server running on your PC, opened up to the internet (and making sure you use a strong password for the SFTP user!). Then you could use the PHP SFTP functions in the SSH2 library to send it: https://www.php.net/manual/en/function.ssh2-sftp.php

            Good suggestion and thanks! It is, in fact, for an old client so, as soon as I get the chance, I'll discuss it with him and see where we go from there.
            Really appreciate your help and that of @maxxd. Many thanks to you both.

              It'd be even more secure to forgo writing a text file at all. Pseudo-code:

              On the server:

              function selectSomeData(){
                if(empty($_GET['key']) || $_GET['key'] !== '123'){
                  die('go away, you!');
                }
                $qry = "SELECT * FROM my_table";
                die($dbConnection->query($qry));
              }
              selectSomeData();

              On the local PC:

              $addr = 'https://path.to.file?key=123';
              $ch = curl_init();
              curl_setopt($ch, CURLOPT_URL, $addr);
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
              $output = curl_exec($ch);
              curl_close($ch);
              
              doSomethingWithData($output);

              Then do a simple exec script or CRON job to run the local script at a regular interval. No text file on the server and you get the data you want.

              Thanks for that suggestion - looks good. I'd totally forgotten about curl functions. I'll have to brush up my skills a bit! 😅. However, I'll certainly give it a try.

                maxxd
                Hi. Sorry to be a nuisance but I'm definitely very rusty these days (been retired - officially - 20 years).
                Looking at the code you suggested for the local machine part, does $addr refer to the file containing the function you suggested for the server end - for example for local testing:
                $addr = http://localhost/curl-server.php?
                I hate to think how many years ago since I last tried CURL! 😅

                sagecelt Looking at the code you suggested for the local machine part, does $addr refer to the file containing the function you suggested for the server end

                Yes. For instance, if you uploaded the server script to https://myawesomesite.com/script, $addr would be https://myawesomesite.com/script?key=123.

                The other option is to simply run it in the browser. Put in some output directives and actually go to the address. That way you wouldn't have to deal with cURL and you could just do it whenever you need/want to.

                maxxd
                I thought I had it with this on the local PC:-
                `<?php

                // Initialize the cURL session
                $addr = 'http://localhost/curl-server.php?key=123'; // for example
                $ch = curl_init();

                // Ask cURL to return the contents in a variable instead of simply echoing them to the browser.
                curl_setopt($ch, CURLOPT_URL, $addr);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

                // Execute the cURL session
                $output = curl_exec($ch);
                // Check if any error occurred ==============================
                if(curl_errno($ch))
                {
                echo 'Curl error: ' . curl_error($ch);
                }
                // Close handle
                curl_close($ch);
                // End error check code =====================================

                echo 'Should now be executing curl-server!!';

                // doSomethingWithData($output);

                ?>That runs and shows the comment on the screen. The next comment is the first line in the server script:echo 'Reached server code ok';`
                but that never gets executed. I must be doing something wrong but I can't see what?

                  Oops - code and ordinary text got screwed up - hope it's understandable?

                    If you are concerned about someone else obtaining sensitive data, it's probably not wise to have it accessible via HTTP. HTTPS does give you some little security because traffic between your "local machine" and the remote server is encrypted in transit and can't easily be snooped by any third party. However, if anyone were to obtain that url, they could also download the text file. Maxxd has a good suggestion to avoid writing the text file if you can. If this step is absolutely necessary, then save it outside of the web root so it cannot be downloaded directly by some random visitor. If your server shows directory indexes, this could be very problematic.

                    Running an SFTP server on your local machine can be a chore to set up and would require you to keep your local machine on whenever this transfer is supposed to happen. If you typically connect to the internet through a router like I do, you'd have to learn how to do port forwarding of SFTP connections to the router to the correct machine on your LAN. NogDog is right that pulling is better.

                    Maxxd has a reasonable suggestion about using a key, but that key is far too simple. If you take that approach, generate a much longer one. Maybe try this code:

                    $token = bin2hex(openssl_random_pseudo_bytes(16));
                    
                    # or in php7
                    $token = bin2hex(random_bytes(16));

                    Another option is to encrypt the file with something like gnupg on the server and email it. BCEncrypt is pretty old now, but might work. It takes some figuring out, but uses serious cryptographic tools to encrypt data so you can email it without worrying too much.

                    As for your curl script, you apparently haven't included the entire script -- the output you describe doesn't correspond to anything in your PHP code.

                      @sagecelt - If I'm reading correctly, you're concerned about not seeing the line 'Reached server code ok' echo to the screen after the line 'Should now be executing curl-server!!'? By the time you get to outputting the line 'Should now be executing curl-server!!', the server script has already been executed. The output of that server script should now be stored in $output thanks to the return transfer directive. So, if you run it again but output $output in your local script, you should see 'Reached server code ok'.

                      That having been said, @sneakyimp makes some very good points and yes, if you do go with a key make it much, much longer and more secure than '123'. Best would be to create and use a true nonce, but that would entail using more than one page or step in getting the data out of the database and to your local computer.

                      maxxd
                      Hi maxxd. You and sneakyimp are incredibly helpful and generous in your professional advice in relation to the question I posed. Thank you both very much indeed: I can’t tell you how much I appreciate it.
                      I am, of course, trying out ideas on my own LAN using Wampserver as the host. In practice I would, of course, use HTTPS and do something about passwords.
                      I must be even rustier than I thought. I seem to be almost there but I’m not getting anything in what I expected to be the return value. Here’s my test code.
                      Local script:-
                      <?php
                      $addr = “http://localhost/curl-server.php?key=123”;
                      $ch = curl_init();
                      curl_setopt($ch, CURLOPT_URL, $addr);
                      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                      $return = curl_exec($ch);
                      if(curl_errno($ch)) {
                      echo “Curl error: “ . curl_error($ch); }
                      curl_close($ch);
                      echo “Script completed <br>”;
                      echo “Output = “ . “ “ . $return;
                      ?>

                      I expected to get a string returned in the variable $return. However, it seems to be empty. This is the server script:-
                      <?php
                      require_once 'forms/incl/config.php';
                      $dsn = 'mysql:host='. $host . ';dbname='. $dbname;
                      if(!$pdo = new PDO($dsn, $user, $password)) {
                      die('PDO setup failed <br>'); }
                      if(!$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC)) {
                      die('setAttribute failed <br>'); }
                      function selectSomeData(){
                      if(empty($_GET['key']) || $_GET['key'] !== '123'){
                      die('You are not authorised!');
                      }
                      $qry = 'We have completed the script.';
                      }
                      selectSomeData();
                      ?>

                      I’m missing something obvious I’m sure but I’m d….d if I can spot it! Sorry for being so dumb over this.

                        Couple things in the scripts you just posted. First - and I have to assume this has to do with copy/paste into the post editor here - all your double quotes are fancy quotes, and that's throwing an error. I don't know what IDE you're using, but if it's formatting text that's going to be an issue - try VSCode or even Notepad++.

                        Second, you don't ever actually echo out $qry in your second script, so nothing gets returned to $return in your first.

                        Lastly, I don't know what 'forms/incl/config.php' looks like, but I assume if it wasn't working you'd see your error message in $return, so it should be good.

                        I ran your scripts (without the include) here, and once $qry was echoed in the second script, everything worked as expected. Turn on error reporting and see if there's anything else throwing a notice or an error.

                        maxxd
                        Thanks. I'm already using VSCode and I only changed the single quotes to double because I thought the single quotes may have messed up my earlier post formatting the code. The use of single quotes in a post to signify code is new to me. All the forums I've ever used in the past used the simple tags "code" and "/code" but included in square brackets; which, after my initial post before editing shows me that it works here too! 😅
                        'forms/incl/config.php' simply contains the actual host, database name, username and password variables.

                        I cut the scripts down just for testing and I could, actually, have left out the whole db enquiry for this exercise.
                        The scripts ran cleanly here and echoed the two text lines at the bottom of the local script so it ran all the way through without throwing an error. I expected $return to contain the string.

                        I can't quite see how to echo out $qry in my second script: having two scripts interlinking is throwing my thinking awry.

                          The double quotes I'm referring to are in the first script - echo “Output = “ . “ “ . $return; instead of echo "Output = "." ".$return; for instance. You can see that the quote marks from your post are curvy, or fancy. Check to make sure they're not that way in VSCode.

                          As for outputting $qry, just literally echo it. Like so: echo $qry;

                          PS: use backticks to signify code in this forum - it recognizes markdown formatting.

                            A little more explanation - the two scripts aren't interlinking at all. The script on the server is just creating an output stream, which the local script is consuming via cURL's RETURNTRANSFER directive. Think of it like this: the server script implicitly calls php://stdout and pipes anything from an echo statement into that stream. The local script implicitly calls php://stdin, creating a destination for the server script's php://stdout contents. So, it's a lot like AJAX in that the scripts aren't actually communicating with each other, they're just putting data out there and assuming that the handler script can actually handle that data.