Dateien verwalten mit Modul jdk.httpserver
ulrich
2024-01-15 8e6840f2eaefe0f7b4763acd5edace0187bf29d3
commit | author | age
7fdd7e 1 /*
U 2   http-cm - File management extensions to jdk.httpserver
3   Copyright (C) 2021  Ulrich Hilger
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU Affero General Public License as
7   published by the Free Software Foundation, either version 3 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18 package de.uhilger.httpserver.cm;
19
8e6840 20 import de.uhilger.httpserver.cm.actor.Zipper;
U 21 import de.uhilger.httpserver.cm.actor.Eraser;
22 import de.uhilger.httpserver.cm.actor.Unzipper;
23 import de.uhilger.httpserver.cm.actor.Renamer;
7fdd7e 24 import com.google.gson.Gson;
U 25 import com.sun.net.httpserver.Authenticator;
26 import com.sun.net.httpserver.Headers;
27 import com.sun.net.httpserver.HttpExchange;
28 import de.uhilger.httpserver.base.HttpResponder;
29 import de.uhilger.httpserver.base.HttpHelper;
30 import de.uhilger.httpserver.base.handler.FileHandler;
31 import de.uhilger.httpserver.image.Datei;
32 import de.uhilger.httpserver.image.ImageActor;
33 import de.uhilger.httpserver.image.ImageThread;
34 import de.uhilger.httpserver.image.ImageThread.ThreadListener;
35 import de.uhilger.httpserver.oauth.BearerAuthenticator;
36 import java.io.BufferedReader;
37 import java.io.File;
38 import java.io.FileOutputStream;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.io.InputStreamReader;
42 import java.io.OutputStream;
43 import java.net.URLDecoder;
44 import java.nio.file.DirectoryStream;
45 import java.nio.file.Files;
46 import java.nio.file.Path;
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.List;
50 import java.util.logging.Logger;
51 import java.util.logging.Level;
52
53 /**
54  * <p>Der FileManager verknuepft einen HTTP-Endpunkt mit einem Ordner des lokalen
55  * Dateisystems.</p>
56  *
57  * <p>HTTP GET fuer eine Datei innerhalb dieses Ordners liefert den Dateiinhalt aus</p>
58  *
59  * <p>HTTP GET fuer einen Ordner liefert eine Liste von dessen Inhalt in JSON</p>
60  *
61  * <p>HTTP PUT fuer eine Datei ueberschreibt eine bestehende Datei mit dem im Body
62  * uebergebenen Inhalt oder legt eine Datei mit diesem Inhalt an</p>
63  *
64  * <p>HTTP POST fuer eine Datei legt eine neue Datei mit dem im Body uebergebenen
65  * Inhalt an oder erzeugt eine neue Datei mit einer laufenden Nummer, falls
66  * diese Datei schon existiert</p>
67  *
68  * <p>HTTP POST fuer einen Ordner legt einen neuen Ordner an wenn er noch nicht
69  * existiert oder erzeugt einen HTTP-Fehler 422</p>
70  *
71  * <p>HTTP DELETE loescht die Liste der Dateien und Ordner im Body</p>
72  *
73  * <p>HTTP PUT ?copyFrom=pfad kopiert die Liste der Datei- oder Ordnernamen im Body
74  * der Anfrage vom Pfad in 'copyFrom' zum Pfad dieser Anfrage. Jede Datei, die
75  * im Ziel bereits existiert, bekommt im Ziel einen neuen Namen mit einer
76  * laufenden Nummer. Bei Ordnern, die im Ziel bereits existieren, bekommt der
77  * betreffende Ordner im Ziel zunaechst einen neuen Namen mit einer laufenden
78  * Nummer, dann wird der Quellordner ans Ziel kopiert.</p>
79  *
80  * <p>HTTP PUT ?moveFrom=pfad verschiebt die Liste der Datei- oder Ordnernamen im
81  * Body der Anfrage vom Pfad in 'moveFrom' zum Pfad dieser Anfrage. Jede Datei,
82  * die im Ziel bereits existiert, bekommt im Ziel einen neuen Namen mit einer
83  * laufenden Nummer. Bei Ordnern, die im Ziel bereits existieren, bekommt der
84  * betreffende Ordner im Ziel zunaechst einen neuen Namen mit einer laufenden
85  * Nummer, dann wird der Quellordner ans Ziel kopiert.</p>
86  *
87  * <p>HTTP PUT mit ?duplicate legt eine Kopie der Datei an</p>
88  *
89  * <p>HTTP PUT mit '?renameTo=neuer Name' benennt die Datei oder den Ordner um,
90  * sofern der neue Name noch nicht vergeben ist</p>
91  *
92  * <p>HTTP PUT mit '?zip' packt den Ordner</p>
93  *
94  * <p>HTTP PUT mit '?unzip' entpackt eine Datei</p>
95  * 
96  * <p>Namenskonventionen:<br>
97  * Ein Pfad mit Schraegstrich ('/') am Ende bezeichnet einen Ordner<br>
98  * Ein Pfad ohne Schraegstrich ('/') am Ende bezeichnet eine Datei</p>
99  *
100  * @author Ulrich Hilger
101  * @version 1, 13. Mai 2021
102  */
103 public class FileManager extends FileHandler implements ThreadListener {
104
105   /*
106   private static final String[] specialChars = {new String("\u00c4"), new String("\u00d6"),
107     new String("\u00dc"), new String("\u00e4"), new String("\u00f6"), new String("\u00fc"), new String("\u00df")};
108   */
109   
110   //public static final String UNWANTED_PATTERN = "[^a-zA-Z_0-9 ]";
111   /* HTTP Methoden */
112
113   public static final String UTF8 = "UTF-8";
114
115   public static final String STR_SLASH = "/";
116   public static final String STR_DOT = ".";
117   
118   public static final String P_COPY = "copyFrom";
119   public static final String P_MOVE = "moveFrom";
120   public static final String P_DUPLICATE = "duplicate";
121   public static final String P_RENAME = "renameTo";
122   public static final String P_ZIP = "zip";
123   public static final String P_UNZIP = "unzip";
124
125   public static final int OP_COPY = 1;
126   public static final int OP_MOVE = 2;
127   public static final int OP_DELETE = 3;
128   
129   public static final String ATTR_ROLE = "role";
130   
131   private final List waitingThreads;
132   private final int maxThreads;
133   private int threadCount;
134   //private String role;
135
136   //public FileManager(String absoluteDirectoryPathAndName, String role, String ctx) {
137   public FileManager() {
138     //super(absoluteDirectoryPathAndName, ctx);
139     //super(absoluteDirectoryPathAndName);
140     waitingThreads = new ArrayList();
141     maxThreads = 4;
142     threadCount = 0;
143     //this.role = role;
144   }
145
146   @Override
147   public void handle(HttpExchange e) throws IOException {
148     Authenticator a = e.getHttpContext().getAuthenticator();
149     if(a instanceof BearerAuthenticator) {
150       BearerAuthenticator auth = (BearerAuthenticator) a;
151       //Realm realm = auth.getRealm();
152       String userId = e.getPrincipal().getUsername();
153       if(auth.hasRole(userId, e.getHttpContext().getAttributes().get(ATTR_ROLE).toString())) {
154         String method = e.getRequestMethod();
5adf10 155         //logger.fine("method: " + method);
7fdd7e 156         HttpHelper helper = new HttpHelper();
U 157         switch (method) {
158           case HttpHelper.HTTP_GET:
159             liste(e, helper);
160             break;
161           case HttpHelper.HTTP_PUT:
162             put(e, helper);
163             break;
164           case HttpHelper.HTTP_POST:
165             speichern(e, helper);
166             break;
167           case HttpHelper.HTTP_DELETE:
168             loeschen(e, helper);
169             break;
170         }
171       } else {
172         standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
173       }
174     } else {
175       standardHeaderUndAntwort(e, SC_FORBIDDEN, "Fehlende Rolle.");
176     }
177   }
178
179   private void put(HttpExchange exchange, HttpHelper helper) throws IOException {
180     String query = exchange.getRequestURI().getQuery();
181     if (query != null) {
182       String[] params = query.split("=");
183       for (String param : params) {
5adf10 184         //logger.fine("param: " + param);
7fdd7e 185       }
U 186       switch (params[0]) {
187         case P_COPY:
188           copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_COPY);
189           break;
190         case P_MOVE:
191           copyOrMove(exchange, params[1], helper.getFileName(exchange), OP_MOVE);
192           break;
193         case P_DUPLICATE:
194           if(Boolean.parseBoolean(params[1])) {
195             String neuerDateiName = duplizieren(exchange, helper);
5adf10 196             //logger.fine("neuer Name: " + neuerDateiName);
7fdd7e 197             standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
U 198           }
199           break;
200         case P_RENAME:
8e6840 201           String neuerDateiName = new Renamer().umbenennen(exchange, helper, params[1]);
5adf10 202           //logger.fine("neuer Name: " + neuerDateiName);
7fdd7e 203           standardHeaderUndAntwort(exchange, SC_OK, neuerDateiName);
U 204           break;
205         case P_ZIP:
206           String path = exchange.getRequestURI().toString();
5adf10 207           //logger.fine(path);
020a97 208           String antwort = new Zipper().packFolder(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
7fdd7e 209           if(antwort.equalsIgnoreCase("ok")) {
U 210             standardHeaderUndAntwort(exchange, SC_OK, antwort);
211           } else {
212             standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
213           }
214           break;
215         case P_UNZIP:
216           path = exchange.getRequestURI().toString();
5adf10 217           //logger.fine(path);
020a97 218           antwort = new Unzipper().extractZipfile(helper.getFileName(exchange), path, exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
7fdd7e 219           if(antwort.equalsIgnoreCase("ok")) {
U 220             standardHeaderUndAntwort(exchange, SC_OK, antwort);
221           } else {
222             standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
223           }
224           break;
225       }
226     } else {
227       speichern(exchange, helper);
228     }
229   }
66173f 230   
U 231   public class DirList {
232     private String pfad;
233     private List<Datei> dateien;
234
235     public String getPfad() {
236       return pfad;
237     }
238
239     public void setPfad(String pfad) {
240       this.pfad = pfad;
241     }
242
243     public List<Datei> getDateien() {
244       return dateien;
245     }
246
247     public void setDateien(List<Datei> dateien) {
248       this.dateien = dateien;
249     }
250     
251     
252   }
7fdd7e 253
U 254   private void liste(HttpExchange e, HttpHelper helper) throws IOException {
255     String path = e.getRequestURI().toString();
5adf10 256     //logger.fine(path);
7fdd7e 257     String fName = helper.getFileName(e);
66173f 258     String dirListPath = e.getHttpContext().getPath() + fName;
7fdd7e 259     if (path.endsWith(STR_SLASH)) {      
5adf10 260       //logger.fine("fName: " + fName);
7fdd7e 261       File dir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fName);
5adf10 262       //logger.fine("absPath: " + dir.getAbsolutePath());
7fdd7e 263       File[] files = dir.listFiles(new ImageFileFilter());
U 264       if(files != null && files.length > 0) {
265         Arrays.sort(files);
266         ArrayList liste = new ArrayList();
267         for (File file : files) {
268           Datei datei = new Datei();
269           String dateiName = file.getName();
270           datei.setName(dateiName);
271           if (file.isDirectory()) {
272             datei.setTyp(Datei.TYP_ORDNER);
273           } else {
274             datei.setTyp(Datei.TYP_DATEI);
275           }
66173f 276           //datei.setPfad(e.getHttpContext().getPath() + fName);
7fdd7e 277           String lowerName = dateiName.toLowerCase();
U 278           if (lowerName.endsWith(ImageActor.JPEG)
279                   || lowerName.endsWith(ImageActor.JPG)
280                   || lowerName.endsWith(ImageActor.PNG)) {
281             datei.setBild(true);
282             String ext = dateiName.substring(dateiName.lastIndexOf(STR_DOT));
283             String ohneExt = dateiName.substring(0, dateiName.lastIndexOf(STR_DOT));
284             datei.setMiniurl(ohneExt + ImageActor.TN + ext);
285             buildImgSrc(file, datei, ohneExt, ext);
286           }
287           liste.add(datei);
288         }
289         while(threadCount > 0) {
290           try {
291             Thread.sleep(50);
292           } catch (InterruptedException ex) {
293             Logger.getLogger(FileManager.class.getName()).log(Level.SEVERE, null, ex);
294           }
295         }
296         if(liste.size() > 0) {
66173f 297           DirList list = new DirList();
U 298           list.setPfad(dirListPath);
299           list.setDateien(liste);
7fdd7e 300           Gson gson = new Gson();
66173f 301           //String json = gson.toJson(liste);
U 302           String json = gson.toJson(list);
7fdd7e 303           //byte[] bytes = json.getBytes();
U 304           //logger.fine("json: '" + json + "'");
305           HttpResponder r = new HttpResponder();
306           r.antwortSenden(e, SC_OK, json);
307         } else {
308           emptyListResponse(e);      
309         }
310       } else {
311         emptyListResponse(e);      
312       }
313     } else {
314       String lowerName = fName.toLowerCase();
315       if(lowerName.contains(ImageActor.B64)) {
316         ImageActor actor = new ImageActor();
317         String fromName = fName.replace(ImageActor.B64, "");
318         File fromFile = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fromName);
319         File toFile = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fName);
5adf10 320         //logger.fine("from " + fromFile.getAbsolutePath() + ", to " + toFile.getAbsolutePath());
7fdd7e 321         if(!toFile.exists()) {
U 322           actor.b64Image(fromFile, toFile);
323         }
324         super.handle(e);
325       } else {
326         super.handle(e);
327       }
328     }
329   }
330   
331   //  data:[<mime type>][;charset=<Zeichensatz>][;base64],<Daten>
332   /*
333   [So. Juni 13 13:23:32 MESZ 2021] FEIN: 
334   file: /home/ulrich/helix-files/bild-test/10419903-14-2-1920-r.jpg, 
335   relname: bild-test/10419903-14-2-1920-r.jpg, ohneExt: 10419903-14-2-1920-r, ext: .jpg (de.uhilger.helix.FileManager buildImgSrc)
336
337   */
338   private void buildImgSrc(File file, Datei datei, String ohneExt, String ext) throws IOException {
339     //logger.fine("file: " + file.getAbsolutePath() + ", ohneExt: " + ohneExt + ", ext: " + ext);
340     File dir = file.getParentFile();
341     String newRelName = ohneExt + ImageActor.TN + ImageActor.B64 + ext;
342     File b64File = new File(dir, newRelName);
343     //logger.fine("b64File: " + b64File.getAbsolutePath());
344     if(!b64File.exists()) {
345       //BildErzeuger be = new BildErzeuger();
346       //be.bildErzeugen(dir, newRelName, BildErzeuger.TN, 120, b64File);
347       ImageThread it = new ImageThread(dir, newRelName, ImageActor.TN, 120, b64File, datei, ext);
348       it.addListener(this);
349       if(threadCount < maxThreads) {
350         ++threadCount;
351         //logger.fine("Thread started, threadCount: " + threadCount);
352         it.start();
353       } else {
354         waitingThreads.add(it);
355         //logger.fine("Thread added to wait queue.");
356       }
357     } else {
358       ImageActor be = new ImageActor();
359       be.setImgSrc(datei, ext, b64File);
360     }
361   }
362   
363   @Override
364   public void finished() {
365     --threadCount;
366     //logger.fine("Thread finished, threadCound now: " + threadCount);
367     if (threadCount < maxThreads) {
368       if (waitingThreads.size() > 0) {
369         Object o = waitingThreads.get(0);
370         if (o instanceof ImageThread) {
371           waitingThreads.remove(o);
372           ImageThread it = (ImageThread) o;
373           ++threadCount;
374           //logger.fine("Thread started from wait queue, threadCount now: " + threadCount);
375           it.start();
376         }
377       }
378     }
379   }  
380   
381   private void emptyListResponse(HttpExchange e) throws IOException {
382     HttpResponder r = new HttpResponder();
383     String json = "{}";
5adf10 384     //logger.log(Level.FINE, "json: ''{0}''", json);
7fdd7e 385     r.antwortSenden(e, SC_OK, json);        
U 386   }
387
388   private void speichern(HttpExchange exchange, HttpHelper helper) throws IOException {
389     String fileName = helper.getFileName(exchange);
5adf10 390     //logger.info("fileName: " + fileName);
7fdd7e 391
U 392     // file ist die Datei, um die es geht
393     File file = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fileName);
394
395     String method = exchange.getRequestMethod();
396     if (fileName.endsWith(STR_SLASH)) {
5adf10 397       //logger.info("neuer Ordner: " + file.getAbsolutePath());
7fdd7e 398       // neuen Ordner erstellen oder ablehnen, wenn der Ordner schon existiert
U 399       if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
400         if (!file.exists()) {
401           file.mkdir();
402           standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
403         } else {
404           String antwort = "Ordner existiert bereits.";
405           standardHeaderUndAntwort(exchange, SC_UNPROCESSABLE_ENTITY, antwort);
406         }
407       } else {
408         String antwort = "PUT fuer neuen Ordner nicht erlaubt, bitte POST verwenden.";
409         standardHeaderUndAntwort(exchange, SC_METHOD_NOT_ALLOWED, antwort);        
410       }
411     } else {
5adf10 412       //logger.info("Datei speichern: " + file.getAbsolutePath());
7fdd7e 413       // Datei speichern
U 414       if (method.equalsIgnoreCase(HttpHelper.HTTP_POST)) {
415         if (file.exists()) {
416           FileTransporter trans = new FileTransporter();
417           file = trans.getNewFileName(file);
418         }
419       } else if (method.equalsIgnoreCase(HttpHelper.HTTP_PUT)) {
420         if (file.exists()) {
421           /*
422             muss delete() sein?
423             pruefen: ueberschreibt der FileWriter den alteen Inhalt oder 
424             entsteht eine unerwuenschte Mischung aus altem und neuem 
425             Inhalt?
426            */
427           file.delete();
428         } else {
429           file.getParentFile().mkdirs();
430         }
431       }
432       // Request Body mit dem Dateiinhalt in einen String lesen
433       StringBuilder sb = new StringBuilder();
434       InputStream is = exchange.getRequestBody();
435       BufferedReader in = new BufferedReader(new InputStreamReader(is));
436       String line = in.readLine();
437       while (line != null) {
438         sb.append(line);
439         line = in.readLine();
440       }
441
442       // dekodieren
443       String content = sb.toString();
5adf10 444       //logger.fine(content);
7fdd7e 445       String decoded = URLDecoder.decode(content, UTF8);
5adf10 446       //logger.fine(decoded);
7fdd7e 447
U 448       // in Datei schreiben
449       byte[] bytes = decoded.getBytes();
450       file.createNewFile();
451       OutputStream os = new FileOutputStream(file);
452       os.write(bytes);
453       os.flush();
454       os.close();
455       is.close();
456
457       // Antwort senden
458       standardHeaderUndAntwort(exchange, SC_OK, file.getAbsolutePath());
459     }
460   }
461
462   private void copyOrMove(HttpExchange exchange, String quelle, String ziel, int op) throws IOException {
5adf10 463     //logger.fine("quelle: " + quelle + ", ziel: " + ziel);
7fdd7e 464     String[] dateiNamen = dateiliste(exchange);
U 465     copyOrMoveFiles(quelle, ziel, dateiNamen, op, exchange);
466     standardHeaderUndAntwort(exchange, SC_OK, "Dateien verarbeitet.");
467   }
468
469   private String copyOrMoveFiles(String fromPath, String toPath, String[] fileNames, int operation, HttpExchange e) throws IOException {
470     String result = null;
471     File srcDir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), fromPath);
472     File targetDir = new File(e.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), toPath);
473     for (String fileName : fileNames) {
474       File srcFile = new File(srcDir, fileName);
5adf10 475       //logger.fine("srcFile: " + srcFile);
7fdd7e 476       if (srcFile.isDirectory()) {
5adf10 477         //logger.fine("srcFile is directory.");
7fdd7e 478         OrdnerBearbeiter bearbeiter = new OrdnerBearbeiter();
U 479         bearbeiter.setTargetDir(targetDir.toPath());
480         bearbeiter.setOperation(operation);
481         Files.walkFileTree(srcFile.toPath(), bearbeiter);
482       } else {
483         Path source = srcFile.toPath();
484         File destFile = targetDir.toPath().resolve(source.getFileName()).toFile();
485         if (destFile.exists()) {
486           FileTransporter trans = new FileTransporter();
487           destFile = trans.getNewFileName(destFile);
488         }
489         if (operation == OP_MOVE) {
490           String fname = srcFile.getName().toLowerCase();
491           if (fname.endsWith(ImageActor.JPEG)
492                   || fname.endsWith(ImageActor.JPG)
493                   || fname.endsWith(ImageActor.PNG)) {
494             moveImgFilesToDirectory(srcFile, srcDir, targetDir, false);
495           } else {
496             Files.move(source, destFile.toPath());
497           }
498         } else {
499           Files.copy(source, destFile.toPath());
500         }
501       }
502     }
503     return result;
504   }
505
506   private void loeschen(HttpExchange exchange, HttpHelper helper) throws IOException {
507     String[] dateiNamen = dateiliste(exchange);
508     String relPfad = helper.getFileName(exchange);
8e6840 509     new Eraser().deleteFiles(relPfad, Arrays.asList(dateiNamen), exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString());
7fdd7e 510     standardHeaderUndAntwort(exchange, SC_OK, "Dateien geloescht.");
U 511   }
512
513   private String[] dateiliste(HttpExchange exchange) throws IOException {
514     String body = new HttpHelper().bodyLesen(exchange);
5adf10 515     //logger.fine("dateien: " + body);
7fdd7e 516     Gson gson = new Gson();
U 517     return gson.fromJson(body, String[].class);
518   }
519
520   public String duplizieren(HttpExchange exchange, HttpHelper helper) throws IOException {
521     String relPfad = helper.getFileName(exchange);
522     File srcFile = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), relPfad);
523     String fnameext = srcFile.getName();
524     int dotpos = fnameext.lastIndexOf(STR_DOT);
525     String fname = fnameext.substring(0, dotpos);
526     String ext = fnameext.substring(dotpos);
527     File srcDir = srcFile.getParentFile();
528     File destFile = new File(srcDir, fname + "-Kopie" + ext);
529     int i = 1;
530     while (destFile.exists()) {
531       destFile = new File(srcDir, fname + "-Kopie-" + Integer.toString(++i) + ext);
532     }
533     Files.copy(srcFile.toPath(), destFile.toPath());
534     return destFile.getName();
535   }
536
537
538   private void moveImgFilesToDirectory(File srcFile, File srcDir, File targetDir, boolean createDestDir) throws IOException {
539     String fnameext = srcFile.getName();
540     int dotpos = fnameext.lastIndexOf(STR_DOT);
541     String fname = fnameext.substring(0, dotpos);
542     String ext = fnameext.substring(dotpos);
5adf10 543     //logger.fine("fname: " + fname + ", ext: " + ext);
7fdd7e 544     Path targetPath = targetDir.toPath();
U 545     DirectoryStream<Path> stream = Files.newDirectoryStream(srcDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
546     for (Path path : stream) {
5adf10 547       //logger.fine(path.getFileName().toString());
7fdd7e 548       //Files.delete(path);
U 549       Files.move(path, targetPath.resolve(path.getFileName()));
550     }
551     stream.close();
552   }
553   
554   private void standardHeaderUndAntwort(HttpExchange exchange, int status, String antwort) throws IOException {
555     Headers resHeaders = exchange.getResponseHeaders();
556     resHeaders.add(CONTENT_TYPE, HttpHelper.CT_TEXT_HTML);
557     new HttpResponder().antwortSenden(exchange, status, antwort);
558   }  
559 }