package javacodebook.thread.imagedownload; /** * Mit Hilfe dieser Klasse werden Bilder einer Webseite heruntergeladen und in * einem vorgegebenen Verzeichnis abgespeichert. */ import javacodebook.regex.html.*; import java.io.*; import java.net.URL; import java.util.Hashtable; public class DownloadImageVisitor implements LinkVisitor { URL absoluteUrl = null; File downloadFolder = null; Hashtable images = new Hashtable(); public DownloadImageVisitor(URL absoluteUrl, File downloadFolder) { this.absoluteUrl = absoluteUrl; this.downloadFolder = downloadFolder; } /** * Lädt ein Bild von der angegebenen Quelle herunter und speichert es im * vorgegebenen Verzeichnis ab. Es wird der Name der Datei, unter dem das * Bild zu finden ist, zurückgegeben. */ public String processLink(String tag, String link, boolean href) { if (href == true) return link; File file; try { // Zunächst feststellen, ob dieser Link schon einmal vorgekommen ist. // Wenn nicht, dann das entsprechende Bild herunterladen und speichern. URL absLink = new URL(absoluteUrl, link); if (images.containsKey(absLink)) file = (File)images.get(absLink); else { // Evtl. gibt es gleiche Bildnamen unter verschiendenen URL's. // Daher muss ein eindeutiger Name gefunden werden. // Anschliessend kann das Bild heruntergeladen werden. file = getFilename(absLink, downloadFolder); images.put(absLink, file); ImageDownloader id = new ImageDownloader(absLink, file); id.start(); } System.out.println(absLink + " -> " + file); return file.toString(); } catch (Exception e) { System.err.println("Konnte nicht bearbeitet werden: " + link); } return link; } /** * Es wird ein eindeutiger Dateiname erzeugt. Zuerst wird der Originalname * ausprobiert. Wenn das fehlschlägt, dann wird der Name solange durch * Anhängen einer laufenden Nummer verändert, bis er eindeutig ist. */ private File getFilename(URL absLink, File folder) throws IOException { String prefix, suffix; File file = new File(absLink.getPath()); int dotIndex = file.getName().lastIndexOf('.'); if (dotIndex > -1) { prefix = file.getName().substring(0, dotIndex); suffix = file.getName().substring(dotIndex); } else { prefix = file.getName(); suffix = ""; } int index = 0; String infix = ""; while (true) { file = new File(folder.toString(), prefix + infix + suffix); if (!file.exists()) break; index++; infix = "_" + index; } return file; } } /** * Dieser Thread lädt das Bild von der URL herunter und speichert es unter dem * vorgegebenen Namen ab. */ class ImageDownloader extends Thread { URL image = null; File file = null; public ImageDownloader(URL image, File file) { this.image = image; this.file = file; } public void run() { try { FileOutputStream out = new FileOutputStream(file); InputStream in = image.openStream(); byte[] buf = new byte[1023]; int len = -1; // Das Bild wird ausgelesen und in die Datei geschrieben while ((len = in.read(buf)) > -1) out.write(buf, 0, len); in.close(); out.close(); } catch (Exception e) { System.err.println("Fehler beim Download einer Datei: " + e.getMessage()); } } } --- Neue Klasse --- package javacodebook.thread.imagedownload; import java.net.URL; import java.io.*; import javacodebook.regex.html.*; /** * Download aller Bilder einer HTML-Seite */ public class Starter { public static void main(String []args) throws Exception { URL url = null; File file = null; try { url = new URL(args[0]); file = new File(args[1]); } catch (Exception e) { printUsage(); return; } // HTML-Seite lesen und alle Bilder herunterladen. String content = readContent(url); LinkVisitor visitor = new DownloadImageVisitor(url, file.getParentFile()); LinkProcessor proc = new LinkProcessor(); String newContent = proc.execute(content, visitor); // Den neuen Inhalt in die angegebene Datei schreiben FileWriter fw = new FileWriter(file); fw.write(newContent); fw.close(); } /** * Liest den gesamten Inhalt der URL in einen String ein. */ public static String readContent(URL url) throws IOException { StringBuffer buf = new StringBuffer(); BufferedReader in = new BufferedReader( new InputStreamReader( url.openStream())); // Resource wird ausgelesen und in einen StringBuffer // geschrieben String inputLine; while ((inputLine = in.readLine()) != null) { buf.append(inputLine); buf.append("\n"); } in.close(); return buf.toString(); } private static void printUsage() { System.out.println("Aufruf: java javacodebook.thread.imagedownload.Starter "); System.exit(0); } }