Lightbox Bilder speichern bzw. downloaden

Es gab ein größeres Lightbox Update, deshalb habe ich das Lightbox Projekt auf GitHub geforkt und angepasst für Version 2.51: https://github.com/nooblucker/lightbox2 

Ich nutze Lightbox v2.05 auf vielen Websites, um Bilder bzw. Bildergalerien ansprechend zu präsentieren. Leider wissen viele User nicht, wie sie das angezeigte Bild speichern bzw. downloaden können. In manchen Browsern funktioniert es über einen Rechtsklick auf den Link und „Ziel speichern unter“. In anderen Browsern wird der Rechtsklick aber von Lightbox abgeblockt. Darum habe ich beschlossen, Lightbox um einen Download-Button zu erweitern.

Hierzu erweitern wir zunächst das LightboxOptions Objekt um eine Variable, die den Pfad zum Download-Button beinhaltet. Dazu öffnen wir die mitgelieferte Datei „lightbox.js“.

LightboxOptions = Object.extend({
    fileLoadingImage:        '/images/loading.gif',
    fileBottomNavCloseImage: '/images/closelabel.gif',
    fileBottomNavDownloadImage: '/images/download-icon.gif',

    overlayOpacity: 0.8,   // controls transparency of shadow overlay

In der selben Datei ändern wir den Konstruktor der Lightbox Klasse, also die Methode initialize. Wir fügen einen Link mit der ID „bottomNavDownload“ und die Download-Grafik hinzu.

Builder.node('div', {id:'imageDataContainer'},
 Builder.node('div',{id:'imageData'}, [
  Builder.node('div',{id:'imageDetails'}, [
   Builder.node('span',{id:'caption'}),
   Builder.node('span',{id:'numberDisplay'})
  ]),
  Builder.node('div',{id:'bottomNav'}, [
   Builder.node('a',{id:'bottomNavDownload', href: '#', target: '_blank' },
    Builder.node('img', { src: LightboxOptions.fileBottomNavDownloadImage })
   ),
   Builder.node('a',{id:'bottomNavClose', href: '#' },
    Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
   )
  ])
 ])
)

Nun müssen wir nur noch das richtige Ziel für den Link setzen. Dazu nutzen wir die updateDetails Methode.

    //
    //  updateDetails()
    //  Display caption, image number, and bottom nav.
    //
    updateDetails: function() {

        this.caption.update(this.imageArray[this.activeImage][1]).show();

        $('bottomNavDownload').href = '/download.php?filename='+$('lightboxImage').src;

Mein Download-Button ist ein Diskettensymbol. Als Ergebnis erhalte ich dann also links neben dem Close-Button das Diskettensymbol. Ein Linksklick öffnet das Bild in einem Download-Dialog. Und zwar erreicht man dies durch die Datei download.php mit folgendem Inhalt:

<?php

// from http://www.php.net/manual/de/function.header.php#102175
function downloadFile( $fullPath ){

 // Must be fresh start
 if( headers_sent() )
 die('Headers Sent');

 // Required for some browsers
 if(ini_get('zlib.output_compression'))
 ini_set('zlib.output_compression', 'Off');

 // File Exists?
 if( file_exists($fullPath) ){

 // Parse Info / Get Extension
 $fsize = filesize($fullPath);
 $path_parts = pathinfo($fullPath);
 $ext = strtolower($path_parts["extension"]);

 // Determine Content Type
 switch ($ext) {
 case "pdf": $ctype="application/pdf"; break;
 case "exe": $ctype="application/octet-stream"; break;
 case "zip": $ctype="application/zip"; break;
 case "doc": $ctype="application/msword"; break;
 case "xls": $ctype="application/vnd.ms-excel"; break;
 case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
 case "gif": $ctype="image/gif"; break;
 case "png": $ctype="image/png"; break;
 case "jpeg":
 case "jpg": $ctype="image/jpg"; break;
 default: $ctype="application/force-download";
 }

 header("Pragma: public"); // required
 header("Expires: 0");
 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
 header("Cache-Control: private",false); // required for certain browsers
 header("Content-Type: $ctype");
 header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );
 header("Content-Transfer-Encoding: binary");
 header("Content-Length: ".$fsize);
 ob_clean();
 flush();
 readfile( $fullPath );

 } else die('File Not Found');
} 

$filename = str_replace("http://www.domain.de", "", $_GET['filename']);
downloadFile(getcwd().$filename);

?>

Je nachdem wie die Website aufgebaut ist, muss man hier Pfade anpassen.

VirtualBox Update von 3.2.12 auf 4.0.4

Habe gerade mein VirtualBox auf den neuesten Stand gebracht. Man soll ja immer alles updaten. Allerdings hat mich das nun 3 Stunden nervenaufreibende Fehlersuche und wilde Googleei gekostet. Denn nach dem Update meldete mein Ubuntu 10.10 ein fehlerhaftes Dateisystem und ich solle doch bitte mit fsck die Fesplatte überprüfen lassen. Das hab ich gemacht, woraufhin tonnenweise Fehler entdeckt und behoben wurden. Nach dem Reboot erschiend jedoch nur noch ein Fehler von wegen irgendeiner invaliden ELF magic und grub rescue: _

Grandios! grub rescue kannte nicht mal den help Befehl, woraufhin ich resignierte. Also eine neue VM erstellt und die Festplatte gemountet. Die Daten konnte ich sichern. Aber die neue VM jetzt nochmal komplett aufsetzen wollte ich auch nicht. Also habe ich das gute alte 3.2.12 parallel installiert. Und siehe da, mein Ubuntu startet wieder, keine Fehler.

Sollte ich jemals herausfinden, wie man diesen Fehler vermeidet / behebt, werde ich darüber schreiben.

NTARS4tw

Atome, Moleküle, Licht

Für alle die bald in Experimentalphysik ihre Diplomprüfung ablegen dürfen: auf dem Tübinger Internet Multimedia Server TIMMS gibt es die dazu passende Vorlesung über Atome, Moleküle und Licht. Die 6. Staffel dieser Soap beinhaltet 44 Folgen.

Darüber hinaus ergötzt sich der geneigte Student am Skript zur Vorlesung, sowie an den F-Praktikumsprotokollen und den Prüfungsprotokollen.

Symfony – Benutzerprofil für sfGuardUser erstellen

Das allseits beliebte Symfony Plugin sfDoctrineGuardPlugin kann leicht um ein beliebig detailreiches Benutzerprofil ergänzt werden. Da die Readme des Plugins nicht mehr auf der Höhe der Zeit ist, möchte ich im Folgenden eine Anleitung geben, wie man das mit Symfony 1.4 und Doctrine macht.

Zunächst definieren wir ein Profil:

# schema.yml
sf_guard_user_profile:
  columns:
    user_id: integer
    photo: varchar(255)
    phone: varchar(20)
  relations:
    type: one
    foreignType: one
    local: user_id
    foreign: id
    onDelete: CASCADE

Durch diese one-to-one Relation kann man von einem sfGuardUser-Objekt auf das Profil folgendermaßen zugreifen:

$profile = $user->getSfGuardUserProfile();
echo $profile->getPhoto(); // liefert das Photo des Profils

Den DocumentRoot bei einem von Plesk verwalteten Apache ändern

Wenn man Domains in Plesk anlegt wird ein Pfad wie zum Beispiel /pfad/zum/vhost/domain.tld/httpdocs als DocumentRoot angelegt. Wenn man diesen ändern möchte auf einen Unterordner, z.B. /pfad/zum/vhost/domain.tld/httpdocs/unterordner kann man einfach in dem Verzeichnis /pfad/zum/vhost/domain.tld/config eine Datei namens vhost.conf anlegen, in die man folgendes reinschreibt:
DocumentRoot /pfad/zum/vhost/domain.tld/httpdocs/unterordner
Dann abspeichern und /etc/init.d/apache2 restart ausführen.

Analog erstellt man für die SSL-verschlüsselte Variante (httpsdocs) eine vhost_ssl.conf im selben Verzeichnis.

Quelle: HostEurope FAQ (to be linked)