1

I want to save a dBase file on a ftp server directly from memory. I use the following simplified snippet. The dBase file is also stored on the server - but it is empty.

What have I done wrong?

Is there a way to do that without first saving the file locally and then transferring it via ftp?

$ftp_conn = ftp_connect($ftpserver);
ftp_login($ftp_conn, $user, $password);
ftp_chdir($ftp_conn, $destination);
$memstream = fopen('php://memory', 'r+');
if ($myClass->create($memstream)) {       // my function around dbase_create() 
    $numRecords = count($myData); 
    if ($numRecords) {
        $myClass->open();                 // my function around dbase_open()
        foreach ($myData as $myRec) {
            $myClass->addRecord($myRec);  // my function around dbase_add_record()
        }
        $myClass->close();                // my function around dbase_close()
        /** the following lines are for debugging
          * they are delivering correct data -
          * so there is still access to the dBase file 
          **/
        $fritzAdr->open();
        print_r($fritzAdr->getRecord(1);
        $fritzAdr->close();
        $fritzAdr->open();
        print_r($fritzAdr->getRecord($fritz->countRecords())
        $fritzAdr->close();
        // but the $memstream is empty!
        rewind($memstream);
        ftp_fput($ftp_conn, 'filename.dbf',  $memstream, FTP_BINARY);
    }
fclose($memstream);
ftp_close($ftp_conn);
Black Senator
  • 449
  • 3
  • 11
  • I wrote corrupt - but it´s just an empty file! Same result, when I follow your hint `if ($numRecords) { $myClass->open(); // my wrapper around dbase_open() foreach ($myData as $myRec) { $myClass->addRecord($myRec); // my wrapper around dbase_add_record() $myClass->close(); // my wrapper around dbase_close() } }` – Black Senator Jan 23 '19 at 08:47
  • As long as I am in the memstream (see above before calling ftp_fput) I can do all the dBase functions like e.g. counting the number of records, outputting individual records (print_r), closing the dBase file, reopening it etc. But the following ftp_fput() of the memstream will only generate an empty file at the destination. – Black Senator Jan 23 '19 at 09:37

2 Answers2

0

You probably need to "close" the database before the upload:

$myClass->close();                // my wrapper around dbase_close()
if ($numRecords) {
    rewind($memstream);
    ftp_fput($ftp_conn, 'filename.dbf',  $memstream, FTP_BINARY);
}

You should also consider saving the database directly to an FTP stream, not to waste memory and time by creating a temporary memory stream:

$stream = fopen("ftp://$user:$password/$ftpserver/$destination/filename.dbf", 'r+');

See Generate CSV file on an external FTP server in PHP.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • @ Martin Prikrl: Unfortunately I have to tell you that your recommendations will not work in this case. No matter if I stay on my way or your recommendation: `fopen (ftp: // ..` follow - only an empty dBase file will be created. Additional your solution also has a conflict with dBase_create:if If I create the file at least the empty file is created - but the normal case will be that the dbf-file already exists and should be overwritten, but this leads to an error, so I would have to additionally check if the File already exists and delete if necessary. – Black Senator Jan 23 '19 at 09:29
0

At the end I have written my own class, which can generate the desired dBase III file: https://github.com/BlackSenator/fritzadr and it worked in the desired way:

$memstream = fopen('php://memory', 'r+');
if ($numRecords) {
    $fritzAdr = new fritzadr();
    foreach ($faxContacts as $faxContact) {
        $fritzAdr->addRecord($faxContact);
    }
    fputs($memstream, $fritzAdr->getDatabase());
    rewind($memstream);
    ftp_fput($ftp_conn, 'fritzadr.dbf', $memstream, FTP_BINARY);
}
fclose($memstream);
ftp_close($ftp_conn);
Black Senator
  • 449
  • 3
  • 11