package javacodebook.jdbc.blobs;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class BlobFileManager {

    public static void main(String[] args) {
        // Wichtig! Diese Pfade müssen auf gültige Pfade
        // gesetzt werden, sonst funktioniert das Beispiel nicht!
        // "inputPath" ist der Ordner, von dem alle Dateien in die
        // Datenbank eingefuegt werden sollen
        String inputPath = "/tmp";

        // "outputPath" ist der Ordner, in den die Dateien aus der
        // Datenbank geschrieben werden
        String outputPath = "/tmp";

        try {
            Class.forName("org.postgresql.Driver");
            Connection con =
                DriverManager.getConnection(
                    "jdbc:postgresql:test",
                    "postgres",
                    "postgres");

            // Die Datenbank von alten Einträgen befreien
            con.createStatement().executeUpdate(
                "DELETE FROM files");

            // Ein PreparedStatement vorbereiten, mit dem gleich
            // die Dateien in die Datenbank gespeichert werden
            PreparedStatement statement =
                con.prepareStatement(
                    "INSERT INTO files(path,content) VALUES(?,?)");

            // Alle Dateien im Ordner "inputPath" öffnen...
            File file = new File(inputPath);
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()) {
                    System.out.println(
                        "-- skipping directory ... "
                            + files[i].getName());
                    continue;
                }
                // ...in das PreparedStatement einfügen...
                statement.setString(1, files[i].getAbsolutePath());
                statement.setBinaryStream(
                    2,
                    new FileInputStream(files[i]),
                    (int) files[i].length());
                System.out.println(
                    "inserting file ... " + files[i].getName());
                // ...und in die Datenbank schreiben
                statement.execute();
            }

            // Nachdem die Dateien jetzt in der Datenbank sind,
            // kann man sich diese mit einem SELECT wieder holen
            ResultSet result =
                con.createStatement().executeQuery(
                    "SELECT path,content FROM files");
            while (result.next()) {
                file = new File(result.getString(1));
                file =
                    new File(new File(outputPath), file.getName());
                System.out.println(
                    "writing file from database ... "
                        + file.getName());

                // Hier wird die Datei geschrieben
                FileOutputStream out = new FileOutputStream(file);
                InputStream in = result.getBinaryStream(2);

                byte[] buffer = new byte[4096];
                int bytes = 0;
                while ((bytes = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytes);
                }
                out.flush();
                out.close();
            }

            // Die Datenbank wieder freimachen
            con.createStatement().executeQuery(
                "DELETE FROM files");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
