Ein einfacher Fileupload ist einfach zu erstellen. Ein <input> vom Typ "file" in eine Form. "method" auf "post" und "action" auf die Zielseite. enctype="multipart/form-data" nicht vergessen und schon ist alles erledigt.
Nun hat diese Implementierung natürlich ihre Grenzen und bei heuten Web-Anwendungen will man oft nicht mehr nur einfach eine Datei hochladen. Man will Bilder vorher bearbeiten und skalieren. Den Fortschritt des Uploads sehen und mehrere Dateien in einer Queue hochladen lassen. Früher nutzte man für sowas Flash.. aber Flash ist tot. Heute hat man HTML5 und JavaScript. Damit kann man alles realisieren was man sich für einen File-Upload wünscht. Die File-API hilft die Dateien zu Laden (aus einem <input> oder auch per Drag and Drop). Per Notification kann man den Benutzer über den Zustand der Uploads informieren, z.B. eine Benachrichtigung ausgeben wenn eine besonders große Datei fertig hochgeladen wurde.
Der hier entworfene File-Upload ist natürlich auch nicht perfekt, aber er funktioniert gut in mehreren Projekten und Scripte um die Hochgeladenen Dateien entgegen zunehmen und zu Speichern, lassen sich gut in PHP oder als Servlet realsieren.
Für Tests reicht ein einfaches PHP-Script:
PHP:
<?php
//see $_REQUEST["lastChunk"] to know if it is the last chunk-part or not
if(isset($_FILES["upfile"])){
file_put_contents($_REQUEST["filename"],file_get_contents($_FILES["upfile"]["tmp_name"]),FILE_APPEND);
}
?>
oder für
Java (FileIOToolKit ist eine eigene Klasse wo append einfach das byte[] an eine Datei ran hängt oder damit eine neue Datei erzeugt, wenn diese noch nicht existieren sollte):
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
try {
String appPath = request.getServletContext().getRealPath("");
String filename = request.getParameter("filename");
for (Part part : request.getParts()) {
if (part.getName().equals("upfile")) {
byte[] out = new byte[part.getInputStream().available()];
part.getInputStream().read(out);
FileIOToolKit.append(appPath + File.separator + filename, out);
System.out.println(appPath + File.separator + filename + " saved!");
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
Wie man hier schon sieht wird die Datei nicht als ganzes hochgeladen sondern in mehreren Stücken. Das hat den Vorteil, dass man sehr sein den Fortschritt beim Upload bestimmen kann.
Das Laden einer Datei ist relativ einfach. Das Drag and Drop oder das onChange einer <input> vom Typ "file" liefern jeweils ein Event, dass die Dateien enthält (es können immer mehrere sein!).
Hier ein einfaches Beispiel, wobei ein boolean verwendet wird, um die beiden Arten zu unterscheiden:
var files = null; // FileList object
if(!nodragndrop){
files=evt.dataTransfer.files; //input
}
else{
files=evt.target.files; //drag and drop
}
Wir werden aber das Laden ignorieren und davon ausgehen, dass man ein File-Object hat, egal ob aus einer Datei oder vielleicht auch vom JavaScript-Code erzeugt (eine Anleitung wie man die Data-URL in sowas umwandelt findet man in einem älteren Beitrag, wo man lernt wie man ein Bild vor dem Upload automatisch verkleinert).
Im nächsten Teil wird das File dann in kleine Teile zerlegt.