luads / php-xbase

A simple parser for *.dbf files using PHP
MIT License
181 stars 83 forks source link

Save inside a temp file #110

Open stg-andrei opened 2 years ago

stg-andrei commented 2 years ago

Hello,

When I create a table, I am trying to save the file inside a temp file instead of an actual file.

I have been playing around with the code but cant seem to quite get it working yet. Is this a feature that needs to be developed or I am not looking in the proper place?

Thanks,

gam6itko commented 2 years ago

@stg-andrei you are creating completely new database file or you adding records to existing database?

stg-andrei commented 2 years ago

I might have to use both. But mainly when I create a new one and add records to it

gam6itko commented 2 years ago

I actually do not understand the issue. When you create new database file you can set any file name you want. When you edit existing file the changes applied to concrete editable file. Editing can be in 2 modes REALTIME and CLONE see:https://github.com/luads/php-xbase/issues/97

stg-andrei commented 2 years ago

Sorry for. the confusion, so what i mean is that when I create the databse I want it to be temporary, I dont want it to remain saved as a local file:

Example flow:

  1. I create the database (as temporary file, https://www.php.net/manual/en/function.tmpfile.php).
  2. I read the file that was created and output it in the browser.
  3. The user saves it in his computer
  4. The database file that was created on the server gets removed automatically.

Code example (but with this approach, after the user saves the file, the file also remains on the server disk, its not temporarty):

$filepath = __DIR__.'/createTable/db.dbf';
if (file_exists($filepath)) {
    unlink($filepath);
}

createFile($filepath);
generateData($filepath, $columnsCount);

function createFile(string $filepath, int $columnsCount = null): void
{
    $header = HeaderFactory::create(TableType::DBASE_III_PLUS_MEMO);

    $tableCreator = new TableCreator($filepath, $header);

        $tableCreator
            ->addColumn(new Column([
                'name'   => "name",
                'type'   => FieldType::CHAR,
                'length' => 20,
            ]))
            ->addColumn(new Column([
                'name' => "birthday",
                'type' => FieldType::DATE,
            ]))
            ->addColumn(new Column([
                'name' => "is_man",
                'type' => FieldType::LOGICAL,
            ]))
            ->addColumn(new Column([
                'name' => "bio",
                'type' => FieldType::MEMO,
            ]))
            ->addColumn(new Column([
                'name'         => "money",
                'type'         => FieldType::NUMERIC,
                'length'       => 20,
                'decimalCount' => 4,
            ]));

    $tableCreator->save()
}

function generateData(string $filepath, int $columnsCount): void
{
    $table = new TableEditor($filepath);

    $date = new \DateTimeImmutable('1970-01-01');

    for ($i = 0; $i < $columnsCount; $i++) {
        $birthday = $date->add(new \DateInterval('P1D'));
        $record = $table->appendRecord()
            ->set("name", "column_$i")
            ->set("birthday", $birthday)
            ->set("is_man", $i % 2 === 0)
            ->set("bio", str_pad('', $i, '-'))
            ->set("money", rand(0, $i) * 0.1);
        $table->writeRecord($record);
    }

    $table
        ->save()
        ->close()
}

header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=db.dbf");
ob_clean(); flush();
readfile( $filepath );    
exit();

Thanks,

gam6itko commented 2 years ago

@stg-andrei Does this code executes with no errors?

stg-andrei commented 2 years ago

Yes, the code executes without any errors. My only issue is that the database file created is note a temporary file. Otherwise is all good I can probably create a cron job to delete the file manually, but I would prefer it to be a temporary file if possibile.

gam6itko commented 2 years ago

@stg-andrei I got it. You request the new feature which allows you create database IN_MEMORY or TEMP_FILE, right? Here we need a little refactoring, I'll do it when I have free time.

stg-andrei commented 2 years ago

"TEMP_FILE " yeah this should be it. If you can pin point me in the right direction, I can contribute maybe

JohnnyQ352 commented 2 weeks ago

Sorry for. the confusion, so what i mean is that when I create the databse I want it to be temporary, I dont want it to remain saved as a local file:

Example flow:

  1. I create the database (as temporary file, https://www.php.net/manual/en/function.tmpfile.php).
  2. I read the file that was created and output it in the browser.
  3. The user saves it in his computer
  4. The database file that was created on the server gets removed automatically.

Code example (but with this approach, after the user saves the file, the file also remains on the server disk, its not temporarty):

$filepath = __DIR__.'/createTable/db.dbf';
if (file_exists($filepath)) {
    unlink($filepath);
}

createFile($filepath);
generateData($filepath, $columnsCount);

function createFile(string $filepath, int $columnsCount = null): void
{
    $header = HeaderFactory::create(TableType::DBASE_III_PLUS_MEMO);

    $tableCreator = new TableCreator($filepath, $header);

        $tableCreator
            ->addColumn(new Column([
                'name'   => "name",
                'type'   => FieldType::CHAR,
                'length' => 20,
            ]))
            ->addColumn(new Column([
                'name' => "birthday",
                'type' => FieldType::DATE,
            ]))
            ->addColumn(new Column([
                'name' => "is_man",
                'type' => FieldType::LOGICAL,
            ]))
            ->addColumn(new Column([
                'name' => "bio",
                'type' => FieldType::MEMO,
            ]))
            ->addColumn(new Column([
                'name'         => "money",
                'type'         => FieldType::NUMERIC,
                'length'       => 20,
                'decimalCount' => 4,
            ]));

    $tableCreator->save()
}

function generateData(string $filepath, int $columnsCount): void
{
    $table = new TableEditor($filepath);

    $date = new \DateTimeImmutable('1970-01-01');

    for ($i = 0; $i < $columnsCount; $i++) {
        $birthday = $date->add(new \DateInterval('P1D'));
        $record = $table->appendRecord()
            ->set("name", "column_$i")
            ->set("birthday", $birthday)
            ->set("is_man", $i % 2 === 0)
            ->set("bio", str_pad('', $i, '-'))
            ->set("money", rand(0, $i) * 0.1);
        $table->writeRecord($record);
    }

    $table
        ->save()
        ->close()
}

header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=db.dbf");
ob_clean(); flush();
readfile( $filepath );    
exit();

Thanks,

I would like to add something here for you. First of all, I totally understand what you are trying to do, but you are going about it the wrong way. Your number one of your example flow is only done with a low level file creation in PhP, not a DBase created file as in XBase tool. So here is my suggestion.

Create the Xbase file, display in browser, allow user to download it and on successful download, use PhP unlink("Full Xbase File Path); and there ya go, file deleted after the download.