Billie
Erfahrenes Mitglied
Hellas liebe Leute!
Nun folgendes, ich habe ein Programm im Grunde fertig geschrieben. Damit meine ich, es tut schon was ich will und das eigentlich in Zufriedenstellendem Maße. Es ist eine WebStart-Anwendung (FileOpenService) welche Bilder lokal verkleinert und anschließend mittels HTTP-Post an einen Server/PHP-Skript schieckt.
Also das Programm ist noch nicht zu 100% fertig, es fehlen noch Kleinigkeiten wie zB die Konfiguration mittels Properties vollständig implementieren und die GUI sperren, während des Uploads (sowie auf JPEG-Endung prüfen, da diese Einstellung von WebStart ignoriert wird). Aber mich würde jetzt mehr interessieren, was ich allgemein in der Struktur/Design verbessern könnte. So damit das Programm wirklich als Objekt-Orientiert abgestempelt werden kann. Ich habe nämlich kein Problem mit dem Verständniss, aber mit der Umsetzung. In jedem Tutorial etc. erlernt man das Prinzip der OOP mithilfe von Autos, Pferden etc. ... aber in einem Programm hatte ich es noch nie mit einem Pferd zu tun, sondern mit elektronischen Elementen die ich nicht anfassen kann, zB Gästebuch, Chat usw. ...
Also der Grundlegende Aufbau sieht so aus, es gibt drei Klassen:
ImageUploadTool
Ist die Hauptklasse und besitzt einfache Methoden wie zB chooseFiles, uploadFiles. Außerdem ein Attribut gui vom Typ ImageUploadToolGUI und eine innere Klasse ImageUploadThread. Diese innere Klasse erledigt in einem das verkleinern und hochladen der einzelnen Bilder. Übrigens, eben diese Klasse weiss ich nicht, wie ich sie kabseln soll.
ImageUploadToolGUI (extends JFrame)
Diese Klasse repräsentiert die gesamte GUI und besitzt eine innere Klasse vom Typ ImageUploadEvents (implements ActionListener, ...) Diese innere Klasse nimmt alle Ereignisse entgegen und ruft die entsprechende Methode der ImageUploadTool-Klasse auf.
DefaultConfiguration extends Properties
Einfach eine Klasse welche vorerst alle Defaultwerte speichert (in naher Zukunft sollten die Defaultwerte von einer XML-Propertie überschrieben werden).
Hier der gesamte Code:
Also bitte helft mir aus meinem kleinen Programm nicht nur ein funktionierendes, sondern auch ein schönes Objektorientiertes zu machen. Es geht mit sehr stark darum, dass auch in späteren Anwendungen anzuwenden.
lg Billie
Nun folgendes, ich habe ein Programm im Grunde fertig geschrieben. Damit meine ich, es tut schon was ich will und das eigentlich in Zufriedenstellendem Maße. Es ist eine WebStart-Anwendung (FileOpenService) welche Bilder lokal verkleinert und anschließend mittels HTTP-Post an einen Server/PHP-Skript schieckt.
Also das Programm ist noch nicht zu 100% fertig, es fehlen noch Kleinigkeiten wie zB die Konfiguration mittels Properties vollständig implementieren und die GUI sperren, während des Uploads (sowie auf JPEG-Endung prüfen, da diese Einstellung von WebStart ignoriert wird). Aber mich würde jetzt mehr interessieren, was ich allgemein in der Struktur/Design verbessern könnte. So damit das Programm wirklich als Objekt-Orientiert abgestempelt werden kann. Ich habe nämlich kein Problem mit dem Verständniss, aber mit der Umsetzung. In jedem Tutorial etc. erlernt man das Prinzip der OOP mithilfe von Autos, Pferden etc. ... aber in einem Programm hatte ich es noch nie mit einem Pferd zu tun, sondern mit elektronischen Elementen die ich nicht anfassen kann, zB Gästebuch, Chat usw. ...
Also der Grundlegende Aufbau sieht so aus, es gibt drei Klassen:
ImageUploadTool
Ist die Hauptklasse und besitzt einfache Methoden wie zB chooseFiles, uploadFiles. Außerdem ein Attribut gui vom Typ ImageUploadToolGUI und eine innere Klasse ImageUploadThread. Diese innere Klasse erledigt in einem das verkleinern und hochladen der einzelnen Bilder. Übrigens, eben diese Klasse weiss ich nicht, wie ich sie kabseln soll.
ImageUploadToolGUI (extends JFrame)
Diese Klasse repräsentiert die gesamte GUI und besitzt eine innere Klasse vom Typ ImageUploadEvents (implements ActionListener, ...) Diese innere Klasse nimmt alle Ereignisse entgegen und ruft die entsprechende Methode der ImageUploadTool-Klasse auf.
DefaultConfiguration extends Properties
Einfach eine Klasse welche vorerst alle Defaultwerte speichert (in naher Zukunft sollten die Defaultwerte von einer XML-Propertie überschrieben werden).
Hier der gesamte Code:
Code:
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.InvalidPropertiesFormatException;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.jnlp.FileOpenService;
import javax.jnlp.FileContents;
import javax.jnlp.ServiceManager;
import javax.jnlp.UnavailableServiceException;
import javax.swing.ImageIcon;
public class ImageUploadTool {
private class ImageUploadThread extends Thread {
private BufferedImage outImg;
private byte[] bytes;
private ByteArrayOutputStream byteStream;
private double ratio;
private double srcWidth;
private double srcHeight;
private Graphics g;
private HttpURLConnection connection;
private int dstWidth;
private int dstHeight;
private int imgMaxSize = 400;
private Iterator iterator;
private ImageWriter imageWriter;
private Image img;
private IIOImage iioImage;
private JPEGImageWriteParam imageWriteParam;
private String boundary = "";
private String content = "";
private URL url= null;
ImageUploadThread() {
imgMaxSize = getImgMaxSize();
imageWriteParam = new JPEGImageWriteParam(Locale.getDefault());
imageWriteParam.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
imageWriteParam.setCompressionQuality(1.0F);
iterator = ImageIO.getImageWritersBySuffix("jpeg");
imageWriter = (ImageWriter) iterator.next();
try {
url = new URL(config.getProperty("url"));
} catch(MalformedURLException e) {
gui.println(e.getMessage());
}
}
public void run() {
for(int i = 0; i < fc.length; i++) {
try {
gui.print(fc[i].getName() + "... ");
img = new ImageIcon(ImageIO.read(fc[i].getInputStream())).getImage();
ratio = 0.0;
srcWidth = (double) img.getWidth(null);
srcHeight = (double) img.getHeight(null);
dstWidth = 0;
dstHeight = 0;
if(srcWidth > imgMaxSize) {
ratio = (imgMaxSize * 100.0) / srcWidth;
dstWidth = imgMaxSize;
dstHeight = (int) (ratio * srcHeight) / 100;
} else if(srcHeight > imgMaxSize) {
ratio = (imgMaxSize * 100.0) / srcHeight;
dstHeight = imgMaxSize;
dstWidth = (int) (ratio * srcWidth) / 100;
} else {
dstWidth = (int) srcWidth;
dstHeight = (int) srcHeight;
}
img = img.getScaledInstance(dstWidth, dstHeight, Image.SCALE_SMOOTH);
outImg = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
g = outImg.getGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
iioImage = new IIOImage(outImg, null, null);
boundary = createBoundary(fc[i].getName());
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
byteStream = new ByteArrayOutputStream(1024);
content = "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"d62c\"; filename=\"" + fc[i].getName() + "\"\r\n"
+ "Content-Type: image/pjpeg\r\n"
+ "\r\n";
bytes = content.getBytes();
byteStream.write(bytes, 0, bytes.length);
imageWriter.setOutput(ImageIO.createImageOutputStream(byteStream));
imageWriter.write(null, iioImage, imageWriteParam);
content = "\r\n--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"code\"\r\n"
+ "\r\n"
+ "1234" + "\r\n"
+ "--" + boundary + "--\r\n";
bytes = content.getBytes();
byteStream.write(bytes, 0, bytes.length);
byteStream.writeTo(connection.getOutputStream());
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
gui.println(connection.getResponseMessage());
} else {
gui.println("ok");
}
byteStream.close();
gui.setProgressValue(i + 1);
} catch(Exception e) {
gui.println(e.getMessage());
}
}
}
}
FileContents fc[] = null;
ImageUploadThread thread = null;
ImageUploadGUI gui = new ImageUploadGUI(this);
Properties config = new Properties(new DefaultConfiguration());
ImageUploadTool() {
}
public String createBoundary(String s) {
String boundary = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(s.getBytes());
byte[] digest = md.digest();
for(int i = 0; i < digest.length; i++) {
boundary += Integer.toHexString(digest[i] & 0xFF);
}
} catch(NoSuchAlgorithmException e) {
boundary = "abcdefghijklmn";
}
return "---------------------------" + boundary;
}
public void chooseFiles() {
try {
FileOpenService fos = (FileOpenService) ServiceManager.lookup("javax.jnlp.FileOpenService");
fc = fos.openMultiFileDialog(null, config.getProperty("extensions").split(","));
} catch(UnavailableServiceException e) {
gui.println(e.getMessage());
} catch(IOException e) {
gui.println(e.getMessage());
}
}
public int getImgMaxSize() {
int imgMaxSize = 400;
try {
imgMaxSize = Integer.parseInt(config.getProperty("imgMaxSize"));
} catch(NumberFormatException e) {
gui.println("NumberFormatException");
}
return imgMaxSize;
}
public void uploadFiles() {
int countFiles = countFiles();
if(countFiles == 0) {
gui.println("Keine Datei(en) ausgewählt.");
} else {
gui.setProgressValue(0);
gui.setProgressMax(countFiles);
if(thread == null) {
thread = new ImageUploadThread();
thread.start();
}
}
}
public int countFiles() {
if(fc == null) return 0;
return fc.length;
}
public static void main(String args[]) {
new ImageUploadTool();
}
}
Code:
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ImageUploadGUI extends JFrame {
private class ImageUploadEvents implements ActionListener {
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if(cmd.equals("chooseFiles")) {
imageUploadTool.chooseFiles();
println(imageUploadTool.countFiles() + " Datei(en) ausgewählt.");
} else if(cmd.equals("uploadFiles")) {
imageUploadTool.uploadFiles();
}
}
}
private GridBagLayout gbl = new GridBagLayout();
private JButton btnSrc = new JButton("Quell-Dateien auswählen");
private JButton btnUpload = new JButton("Upload");
private JLabel lblUpload = new JLabel("Upload-Code:");
private JProgressBar progrs = new JProgressBar();
private JScrollPane conScroll = new JScrollPane();
private JTextArea con = new JTextArea("http://www.pukemusic.at/\r\nby Andreas Fagschlunger\r\n\r\n");
private JTextField txtPwd = new JTextField();
private ImageUploadTool imageUploadTool;
private ImageUploadEvents imageUploadEvents = new ImageUploadEvents();
ImageUploadGUI(ImageUploadTool imageUploadTool) {
super("ImageUploadTool v 1.1");
this.imageUploadTool = imageUploadTool;
initComponents();
setSize(400, 300);
setLocationRelativeTo(null);
setVisible(true);
}
private void initComponents() {
setLayout(gbl);
gbl.setConstraints(conScroll, new GridBagConstraints(0, 0, 2, 1, 100, 100, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0));
gbl.setConstraints(btnSrc, new GridBagConstraints(0, 1, 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets( 0, 10, 10, 10), 0, 0));
gbl.setConstraints(lblUpload, new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 0, 10, 10, 5), 0, 0));
gbl.setConstraints(txtPwd, new GridBagConstraints(1, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets( 0, 0, 10, 10), 0, 0));
gbl.setConstraints(btnUpload, new GridBagConstraints(0, 3, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets( 0, 10, 10, 10), 0, 0));
gbl.setConstraints(progrs, new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets( 0, 0, 10, 10), 0, 0));
// GUI settings
conScroll.setViewportView(con);
con.setEditable(false);
con.setLineWrap(true);
con.setMargin(new Insets(0, 5, 0, 5));
progrs.setStringPainted(true);
// setActionCommand
btnSrc.setActionCommand("chooseFiles");
btnUpload.setActionCommand("uploadFiles");
// addActionListener
btnSrc.addActionListener(imageUploadEvents);
btnUpload.addActionListener(imageUploadEvents);
add(conScroll);
add(btnSrc);
add(lblUpload);
add(txtPwd);
add(btnUpload);
add(progrs);
}
public void print(String s) {
con.append(s);
con.setCaretPosition(con.getText().length());
}
public void println(String s) {
print(s + "\r\n");
}
public void setProgressMax(int n) {
progrs.setMaximum(n);
}
public void setProgressValue(int n) {
progrs.setValue(n);
}
}
Code:
import java.util.Properties;
public class DefaultConfiguration extends Properties {
DefaultConfiguration() {
setProperty("url", "http://localhost:80/batch_upload.php");
setProperty("extensions", "jpg,jpeg");
setProperty("imgMaxSize", "400");
}
}
Also bitte helft mir aus meinem kleinen Programm nicht nur ein funktionierendes, sondern auch ein schönes Objektorientiertes zu machen. Es geht mit sehr stark darum, dass auch in späteren Anwendungen anzuwenden.
lg Billie