0

I would like to be able to save a JSON file that is in a database to the user's PC. In summary, I'm storing setup files from a sim racing game, that use a JSON format, in a database, and I'd like the user to be able to upload/download these JSON files (to share with others, etc).

I've got the upload working, using PDO, so there is a column called setup that is a text data type. I'm using a form, with a $FILES() to fetch the uploaded json file, with some checks to ensure it's a valid setup json.

$setup = file_get_contents($_FILES['setupjson']['tmp_name']); //get json from file uploaded

$setupJSON = json_decode($setup); //decode into object
$car = $setupJSON->carName; //carName from object

if ($obj->searchCarName($car) > 0)   // if search matches (car exists)
   {
        if($obj->insertSingleSetup($_POST["name"], $_POST["description"], $_POST["type"], $car, $_POST["track"], $setup) !== false)
        {
            header('Location: add.php?success');
            exit();
        }
        else
        {
            header('Location: add.php?error=Error+adding+the+setup');
            exit();
        }
   }
else
    {
    header('Location: add.php?error=Please+submit+a+valid+setup');
    exit();
    }
}

The issue i'm having is downloading the file again. I've been able to view the JSON directly

<?php
include('../db.php');

$setup_id = $_POST['setup'];

try {
        $connectionString = sprintf("mysql:host=%s;dbname=%s;charset=utf8mb4",
                DB::DB_HOST,
                DB::DB_NAME);

    $pdo = new PDO($connectionString, DB::DB_USER, DB::DB_PASSWORD);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

    $sql = 'SELECT * FROM setups WHERE setup_id= :setupID';

    $query = $pdo->prepare($sql);
    $query->bindValue(':setupID', $setup_id);
    $result = $query->execute();
    $setup = $query->fetch(PDO::FETCH_ASSOC);
    processSetup($setup);

} catch (PDOException $e) {
    die("Could not connect to the database $dbname :" . $e->getMessage());
}

function processSetup($setupRow)
{
    $setup = $setupRow['setup'];
    $setupJSON = json_decode($setup);
    echo '<pre>';
    echo $setup; 
    echo '</pre>';
}



?>

but I can't work out how to download it. I've researched that it's related to headers, but everytime I try something, it never works. I just want the save file dialog to appear with the json, and preferably, the option to set the filename outputted to a chosen variable.

MorGuux
  • 53
  • 5
  • 2
    Your code might still be vulnerable to SQL injection, because you have not specified charset in your DSN string See [Are PDO prepared statements sufficient to prevent SQL injection?](https://stackoverflow.com/a/12202218/1839439) – Dharman Jun 08 '19 at 20:32
  • Where would ```$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); ```be inserted? – MorGuux Jun 08 '19 at 20:37
  • It would still be a good idea nonetheless to put the correct connection charset in DSN. i.e. `utf8mb4` https://phpdelusions.net/pdo#dsn – Dharman Jun 08 '19 at 20:43
  • @Dharman like what i've edited? – MorGuux Jun 08 '19 at 20:45
  • Okay great, lesson learned for the future. Now to work out the main issue :D – MorGuux Jun 08 '19 at 20:50

1 Answers1

1

Just figured it out, on the processSetup function, I changed the code to this

function processSetup($setupRow)
{
    $setup = $setupRow['setup'];
    header('Content-type: application/json');
    header('Content-disposition: attachment; filename=setup.json'); 
    echo $setup;
}

If I add some code to give the JSON it's proper filename, it'll be perfect :D

MorGuux
  • 53
  • 5
  • What about if you try the original code, but without `
    ` tags and use `json_encode($setup, \JSON_FORCE_OBJECT)`?
    – Dharman Jun 08 '19 at 22:00