Tabelle Auslesen fehlende Images downloaden

leo_nie

Grünschnabel
Ich bräuchte ein wenig Hilfe.
Ich habe eine MySQL DB mit einer Tabelle 'images'. Hier sind im Feld 'image' die Bildurl gespeichert.
Die Bilder werden gedownload und in ein Verzeichnis gespeichert. Im DB-Feld 'image_server' wird der Pfad zum Server gespeichert.

Jetzt möchte ich folgendes:
1. Zuerst soll überprüft werden welche Bilder noch im Verzeichnis fehlen
2. die fehlenden Bilder sollten automatisch gedownloaded werden und im Verzeichnis gespeichert werden
3. Im DB-Feld 'image_server' sollte automatisch die entsprechende Dateiname gespeichert werden

Wie kann ich hier am besten vorgehen? Welcher ist am schnellsten?
 
Hi

was steht denn in den Pfaden der noch nicht geladenen Bilder? Leer oder falscher Pfad oder...?
Ist das ganze eine einmalige Aktion, oder soll das regelmäßig passieren, oder durch Benutzer ausgelöst (alle oder pro Benutzer nur bestimmte oder)...?

Hast du schon einen Codeversuch für einen Teil?
 
Das sollte regelmäßig passieren vom Benutzer angestoßen werden oder noch besser als cronjob übernacht laufen. Die URL-Pfaden stehen alle in der Datenbank im Feld image, die Felder mit 'image_server is null' sollten selektiert werden.
z.B. Tabelle artikelbilder
Datensatz 1
Feld Artikelnr: Artikel100
Feld Image: www.artikelbilderzeigen.de/image100.jpg
Feld Image_server: /html/artikelbilderzeigen/bilder/image100.jpg
Datensatz 2
Feld Artikelnr: Artikel200
Feld Image: www.artikelbilderzeigen.de/image200.jpg
Feld Image_server: <null>

Selektieren alle Datensätze die noch nicht runter geladen sind
Select artikelnr, image, from artikelbilder where image_server is null

Für jeden Datensatz muss jetzt folgendes passieren:
- runterladen www.artikelbilderzeigen.de/image200.jpg in das Server-Verzeichnis /html/artikelbilderzeigen/bilder/
- Update artikelbilder set Image_server = '/html/artikelbilderzeigen/bilder/image200.jpg' where artikelnr = artikelnr_variable

Code versuch
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT produktnr,image FROM artikelbilder where image_server ist null";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$image = $row["image"];
$produktnr= $row["produktnr"]

//Hier wird die Datei runtergeladen und gespeichert
$contents= file_get_contents($image);
$savename = $image;

$savefile = fopen("$savename.jpg", "w");
fwrite($savefile, $contents);
fclose($savefile);

//Hier wird die Dateiname in der Tabelle gespeichert
$neue_image_server['image_server'] = $savefile;

$sth = $dbh->prepare('UPDATE artikelbilder SET imageserver = :image_server where produktnr= :produktnr');
$sth->execute(array(':image_server' => $image_server, ':produktnr' => $produktnr));

}
} else {
echo "0 results";
}
$conn->close();
?>
 
Okay jetzt habe ich es raus gefunden

so funktiontiert es:
<?php

$pdo = new PDO('mysql:host=localhost;dbname=??', '??', '??');

$sql = "SELECT * FROM artikelbilder where ximage_server ='' ";
foreach ($pdo->query($sql) as $row) {

$produktnr = $row['Xproduktid'];
$imageURL = $row['Ximage'];

//get extension of image
$ext = pathinfo($imageURL, PATHINFO_EXTENSION);
$file = basename($imageURL,".".$ext);

$newfile = $produktnr."-".$file.".".$ext;
echo $newfile."<br />";

//Local path of image - where will we save the image
$downloadTo = fopen($newfile, 'wb');

//Download and save image
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $imageURL);
curl_setopt($ch, CURLOPT_FILE, $downloadTo);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
curl_close($ch);

//Update image_server Filename
$statement = $pdo->prepare("UPDATE artikelbilder SET ximage_server= :image_server where xproduktid = :xproduktid and ximage = :imageURL");
$statement->execute(array('image_server'=> $newfile, 'imageURL' => $imageURL, 'xproduktid' =>$produktnr ));

echo "Gespeichert"."<br />";
}



Jetzt möchte ich aber noch gerne die Bilder um 40% verkleinern. Kann jemand hier behilflich sein?
 
Okay, alles klar. Auch funktioniert jetzt wunderbar, aber leider bricht das script ab: Maximum execution time exceeded.
Kann ich dies irgendwie umgehen oder was kann man da am besten machen?



Code:
<?php

const IMAGE_HANDLERS = [
    IMAGETYPE_JPEG => [
        'load' => 'imagecreatefromjpeg',
        'save' => 'imagejpeg',
        'quality' => 100
    ],
    IMAGETYPE_PNG => [
        'load' => 'imagecreatefrompng',
        'save' => 'imagepng',
        'quality' => 0
    ],
    IMAGETYPE_GIF => [
        'load' => 'imagecreatefromgif',
        'save' => 'imagegif'
    ]
];

/**
 * @param $src - a valid file location
 * @param $dest - a valid file target
 * @param $targetWidth - desired output width
 * @param $targetHeight - desired output height or null
 */
function createThumbnail($src, $dest, $targetWidth, $targetHeight = null) {

    // 1. Load the image from the given $src
    // - see if the file actually exists
    // - check if it's of a valid image type
    // - load the image resource

    // get the type of the image
    // we need the type to determine the correct loader
    $type = exif_imagetype($src);

    // if no valid type or no handler found -> exit
    if (!$type || !IMAGE_HANDLERS[$type]) {
        return null;
    }

    // load the image with the correct loader
    $image = call_user_func(IMAGE_HANDLERS[$type]['load'], $src);

    // no image found at supplied location -> exit
    if (!$image) {
        return null;
    }


    // 2. Create a thumbnail and resize the loaded $image
    // - get the image dimensions
    // - define the output size appropriately
    // - create a thumbnail based on that size
    // - set alpha transparency for GIFs and PNGs
    // - draw the final thumbnail

    // get original image width and height
    $width = imagesx($image);
    $height = imagesy($image);

    // maintain aspect ratio when no height set
    if ($targetHeight == null) {

        // get width to height ratio
        $ratio = $width / $height;

        // if is portrait
        // use ratio to scale height to fit in square
        if ($width > $height) {
            $targetHeight = floor($targetWidth / $ratio);
        }
        // if is landscape
        // use ratio to scale width to fit in square
        else {
            $targetHeight = $targetWidth;
            $targetWidth = floor($targetWidth * $ratio);
        }
    }

    // create duplicate image based on calculated target size
    $thumbnail = imagecreatetruecolor($targetWidth, $targetHeight);

    // set transparency options for GIFs and PNGs
    if ($type == IMAGETYPE_GIF || $type == IMAGETYPE_PNG) {

        // make image transparent
        imagecolortransparent(
            $thumbnail,
            imagecolorallocate($thumbnail, 0, 0, 0)
        );

        // additional settings for PNGs
        if ($type == IMAGETYPE_PNG) {
            imagealphablending($thumbnail, false);
            imagesavealpha($thumbnail, true);
        }
    }

    // copy entire source image to duplicate image and resize
    imagecopyresampled(
        $thumbnail,
        $image,
        0, 0, 0, 0,
        $targetWidth, $targetHeight,
        $width, $height
    );


    // 3. Save the $thumbnail to disk
    // - call the correct save method
    // - set the correct quality level

    // save the duplicate version of the image to disk
    return call_user_func(
        IMAGE_HANDLERS[$type]['save'],
        $thumbnail,
        $dest,
        IMAGE_HANDLERS[$type]['quality']
    );
  
  

}


$file = 'image_protokoll.txt';
$current = file_get_contents($file);
$current ="Images die nicht geladen werden konnten:\n";
// Schreibt den Inhalt in die Datei zurück
file_put_contents($file, $current);

$pdo = new PDO('mysql:host=localhost;dbname=??', '??', '??');

$sql = "SELECT * FROM artikelbilder where ximage_server IS NULL or ximage_server = '' ";

foreach ($pdo->query($sql) as $row) {
   $produktnr = $row['xproduktid'];
   $imageURL = $row['ximage'];
   //Manchmal ist in der url ein leerzeichen bei der Marke,dies muss abgefangen werden
   $imageURL = str_replace(' ', '%20', $imageURL); 

    //get extension of image
    $ext = pathinfo($imageURL, PATHINFO_EXTENSION);
    $file = basename($imageURL,".".$ext);
  
    $newfile = $produktnr."-".$file.".".$ext;
    $newfilethum = $produktnr."-".$file."-thumb".".".$ext;
  
  
    //Local path of image - where will we save the image
    $downloadTo = fopen($newfile, 'wb');

    //Download and save image
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $imageURL);
    curl_setopt($ch, CURLOPT_FILE, $downloadTo);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    $output = curl_exec($ch);
    curl_close($ch);
  
    //Verkleinern
    createThumbnail($newfile, $newfilethum, 200);
 
      //Update image_server Filename nur update wenn Datei auch tatsächlich besteht
    if(!file_exists($newfilethum))
    {
        $file = 'image_protokoll.txt';
        // Öffnet die Datei, um den vorhandenen Inhalt zu laden
        $current = file_get_contents($file);
        // Fügt eine neue Person zur Datei hinzu
        $current .= $produktnr." - ".$imageURL."\n";
        // Schreibt den Inhalt in die Datei zurück
        file_put_contents($file, $current);
      
        
    } else {
 
        $statement = $pdo->prepare("UPDATE artikelbilder SET ximage_server= :image_server where xproduktid = :xproduktid and ximage = :imageURL");
        $statement->execute(array('image_server'=> $newfilethum, 'imageURL' => $imageURL, 'xproduktid' =>$produktnr ));
  
    }

  
  
}


?>
 
Idealerweise nicht vom Browser heraus aufrufen, sondern wie oben schon geplant als Cronjob laufen lassen (CLI-Version von PHP).
 
Zurück