Klassenbiliothek fuer Dateiverwaltung
7 files modified
2 files added
2 files deleted
550 ■■■■■ changed files
src/de/uhilger/fm/Const.java 44 ●●●●● patch | view | raw | blame | history
src/de/uhilger/fm/CopyMoveVisitor.java 119 ●●●●● patch | view | raw | blame | history
src/de/uhilger/fm/Deflator.java 4 ●●● patch | view | raw | blame | history
src/de/uhilger/fm/Eraser.java 19 ●●●●● patch | view | raw | blame | history
src/de/uhilger/fm/FileOpsVisitor.java 176 ●●●●● patch | view | raw | blame | history
src/de/uhilger/fm/ImageFileFilter.java 23 ●●●● patch | view | raw | blame | history
src/de/uhilger/fm/Lister.java 17 ●●●● patch | view | raw | blame | history
src/de/uhilger/fm/Mover.java 56 ●●●● patch | view | raw | blame | history
src/de/uhilger/fm/Renamer.java 30 ●●●● patch | view | raw | blame | history
src/de/uhilger/fm/dateiliste-beispiel.json 27 ●●●●● patch | view | raw | blame | history
src/de/uhilger/fm/package-info.java 35 ●●●●● patch | view | raw | blame | history
src/de/uhilger/fm/Const.java
File was deleted
src/de/uhilger/fm/CopyMoveVisitor.java
File was deleted
src/de/uhilger/fm/Deflator.java
@@ -32,6 +32,8 @@
 * @author Ulrich Hilger, 15. Januar 2024
 */
public class Deflator {
  private final String STR_SLASH = "/";
  /* --------------- Ordner packen ----------------- */
  /**
@@ -51,7 +53,7 @@
      try {
        //String fName = getFileName(e);
        //logger.fine("fName: " + fName);
        if (fName.endsWith(Const.STR_SLASH)) {
        if (fName.endsWith(STR_SLASH)) {
          File dir = new File(base, fName);
          if (dir.isDirectory()) {
            //logger.fine("absPath: " + dir.getAbsolutePath());
src/de/uhilger/fm/Eraser.java
@@ -30,19 +30,24 @@
 * @author Ulrich Hilger, 15. Januar 2024
 */
public class Eraser {
  public static final int OP_DELETE = 3;
  private final String STR_DOT = ".";
  public String deleteFiles(String relPath, List<String> fileNames, String base) {
    String result = null;
    try {
      //logger.fine(fileNames.toString());
      if (!relPath.startsWith(Const.STR_DOT)) {
      if (!relPath.startsWith(STR_DOT)) {
        File targetDir = new File(base, relPath); // getTargetDir(relPath);
        //logger.fine("targetDir: " + targetDir);
        for (String fileName : fileNames) {
          File targetFile = new File(targetDir, fileName);
          //logger.fine(targetFile.getAbsolutePath());
          if (targetFile.isDirectory()) {
            CopyMoveVisitor bearbeiter = new CopyMoveVisitor();
            bearbeiter.setOperation(Const.OP_DELETE);
            FileOpsVisitor bearbeiter = new FileOpsVisitor();
            bearbeiter.setOperation(OP_DELETE);
            Files.walkFileTree(targetFile.toPath(), bearbeiter);
          } else {
            /*
@@ -51,9 +56,9 @@
                die so heissen, also z.B. alle [Dateiname]*.jpg
             */
            String fname = targetFile.getName().toLowerCase();
            if (fname.endsWith(Const.JPEG)
                    || fname.endsWith(Const.JPG)
                    || fname.endsWith(Const.PNG)) {
            if (fname.endsWith(ImageFileFilter.JPEG)
                    || fname.endsWith(ImageFileFilter.JPG)
                    || fname.endsWith(ImageFileFilter.PNG)) {
              deleteImgFiles(targetDir, targetFile);
            } else {
              targetFile.delete();
@@ -70,7 +75,7 @@
  private void deleteImgFiles(File targetDir, File targetFile) throws IOException {
    String fnameext = targetFile.getName();
    int dotpos = fnameext.lastIndexOf(Const.STR_DOT);
    int dotpos = fnameext.lastIndexOf(STR_DOT);
    String fname = fnameext.substring(0, dotpos);
    String ext = fnameext.substring(dotpos);
    //logger.fine("fname: " + fname + ", ext: " + ext);
src/de/uhilger/fm/FileOpsVisitor.java
New file
@@ -0,0 +1,176 @@
/*
  fm - File management class library
  Copyright (C) 2024  Ulrich Hilger
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Affero General Public License for more details.
  You should have received a copy of the GNU Affero General Public License
  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package de.uhilger.fm;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
/**
 * Ein FileVisitor zum Verschieben, Kopieren oder Loeschen ganzer Ordnerstrukturen mit
 * Hilfe der Methode Files.walkFileTree von java.nio.
 *
 * @author Ulrich Hilger
 * @version 1, 14. Mai 2021
 */
public class FileOpsVisitor extends FileHelper implements FileVisitor {
  private Path targetDir;
  private int operation;
  /**
   * Den Zielordner fuer Kopier- oder Verschiebeoperationen angeben
   *
   * @param targetDir der Zielordner
   */
  public void setTargetDir(Path targetDir) {
    this.targetDir = targetDir;
  }
  /**
   * Die gewuenschte Dateioperation angeben,
   * OP_COPY, OP_MOVE oder OP_DELETE
   *
   * @param op die Dateioperation
   */
  public void setOperation(int op) {
    this.operation = op;
  }
  /**
   * Dafuer sorgen, dass beim Kopieren oder Verschieben kein am Ziel bereits existierender
   * Ordner ueberschrieben wird, indem am Ziel fuer einen bereits existierenden Ordner ein
   * anderer Name mit laufender Nummer erzeugt wird.
   *
   * Invoked for a directory before entries in the directory are visited. If this method
   * returns CONTINUE, then entries in the directory are visited. If this method returns
   * SKIP_SUBTREE or SKIP_SIBLINGS then entries in the directory (and any descendants)
   * will not be visited.
   *
   * @param dir Zielordner
   * @param attrs die gewuenschten Attribute
   * @return gibt stets FileVisitResult.CONTINUE zurueck
   * @throws IOException wenn etwas schief geht
   */
  @Override
  public FileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs)
          throws IOException {
    if (operation != Eraser.OP_DELETE) {
      if (dir instanceof Path) {
        Path sourceDir = (Path) dir;
        File destFile = targetDir.resolve(sourceDir.getFileName()).toFile();
        //logger.fine("sourceDir: " + sourceDir + ", destFile: " + destFile);
        if (destFile.exists()) {
          File newDir = getNewFileName(destFile);
          destFile.renameTo(newDir);
        }
        destFile.mkdir();
        this.targetDir = destFile.toPath();
        //logger.fine("targetDir now: " + targetDir.toString());
      }
    }
    return FileVisitResult.CONTINUE;
  }
  /**
   * Fuer jede Datei die gewuenschte Dateioperation ausführen
   *
   * Invoked for a file in a directory.
   *
   * @param file  die zu bearbeitende Datei a reference to the file
   * @param attrs  the directory's basic attributes
   * @return  stets FileVisitResult.CONTINUE
   * @throws IOException wenn etwas schief geht
   */
  @Override
  public FileVisitResult visitFile(Object file, BasicFileAttributes attrs) throws IOException {
    if(operation != Eraser.OP_DELETE) {
      if (file instanceof Path) {
        Path source = (Path) file;
        File destFile = targetDir.resolve(source.getFileName()).toFile();
        if (destFile.exists()) {
          destFile = getNewFileName(destFile);
        }
        if (operation == Mover.OP_MOVE) {
          Files.move(source, destFile.toPath());
        } else if (operation == Mover.OP_COPY) {
          Files.copy(source, destFile.toPath());
        }
      }
    } else {
     Files.delete((Path) file);
    }
    return FileVisitResult.CONTINUE;
  }
  /**
   * Bei diesem Visitor bleibt diese Methode ungenutzt, hier muessten noch Faelle
   * behandelt werden, die zu einem Abbruch fuehren und ggf. ein Rollback realisiert werden.
   *
   * Invoked for a file that could not be visited. This method is invoked if the file's attributes
   * could not be read, the file is a directory that could not be opened, and other reasons.
   *
   * @param file  die Datei, bei der es zum Abbruch kam
   * @param exc  the I/O exception that prevented the file from being visited
   * @return stets FileVisitResult.CONTINUE
   * @throws IOException wenn etwas schief laeuft
   */
  @Override
  public FileVisitResult visitFileFailed(Object file, IOException exc) throws IOException {
    return FileVisitResult.CONTINUE;
  }
  /**
   * Fuer jede Datei Schritte ausfuehren, wie sie sich nach einer Dateioperation ergeben.
   * Hier wird beim Verschieben von Dateien das Quellverzeichnis geloescht, nachdem es zum
   * Ziel uebertragen wurde.
   *
   * Invoked for a directory after entries in the directory, and all of their descendants,
   * have been visited. This method is also invoked when iteration of the directory completes
   * prematurely (by a visitFile method returning SKIP_SIBLINGS, or an I/O error when
   * iterating over the directory).
   *
   * @param dir   der fertig durchlaufene Quellordner
   * @param exc  null if the iteration of the directory completes without an error; otherwise
   * the I/O exception that caused the iteration of the directory to complete prematurely
   * @return
   * @throws IOException
   */
  @Override
  public FileVisitResult postVisitDirectory(Object dir, IOException exc) throws IOException {
    if (operation != Eraser.OP_DELETE) {
      if (dir instanceof Path) {
        Path finishedDir = (Path) dir;
        targetDir = targetDir.getParent();
        if(operation == Mover.OP_MOVE) {
          //logger.fine("delete " + finishedDir.toString());
          Files.delete(finishedDir);
        }
      }
      //logger.fine("targetDir now: " + targetDir.toString());
    } else {
      Files.delete((Path) dir);
    }
    return FileVisitResult.CONTINUE;
  }
}
src/de/uhilger/fm/ImageFileFilter.java
@@ -27,15 +27,28 @@
 * @version 1, 12. Mai 2021
 */
public class ImageFileFilter implements FileFilter {
  public static final String JPG = ".jpg";
  public static final String JPEG = ".jpeg";
  public static final String PNG = ".png";
  public static final String B64 = "_b64"; // Base64-Encoded
  public static final String TN = "_tn"; // 120
  public static final String KL = "_kl"; // 240
  public static final String SM = "_sm"; // 500
  public static final String MT = "_mt"; // 700
  public static final String GR = "_gr"; // 1200
    @Override
    public boolean accept(File pathname) {
      boolean pass = true;
      String fname = pathname.getName().toLowerCase();
      if(fname.endsWith(Const.JPEG) ||
              fname.endsWith(Const.JPG) || fname.endsWith(Const.PNG)) {
        if(fname.contains(Const.GR) || fname.contains(Const.KL) ||
                fname.contains(Const.MT) || fname.contains(Const.SM) ||
                fname.contains(Const.TN) || fname.contains(Const.B64)) {
      if(fname.endsWith(JPEG) ||
              fname.endsWith(JPG) || fname.endsWith(PNG)) {
        if(fname.contains(GR) || fname.contains(KL) ||
                fname.contains(MT) || fname.contains(SM) ||
                fname.contains(TN) || fname.contains(B64)) {
          pass = false;
        }
      }
src/de/uhilger/fm/Lister.java
@@ -41,6 +41,15 @@
  public static final String STR_DOT = ".";
  /**
   *
   * @param fName Name und relativer Pfad des Ordners, dessen Inhalt aufgelistet werden soll
   * @param ctxPath  Kontext Pfad zur Bildung des URL, der auf die Miniaturansicht verweist
   * (koennte evtl. im Client gebildet werden, hier dann nur Mini-Dateiname zurueckgeben)
   * @param base  Basisverzeichnis, gegen das der relative Pfad aufgeloest werden soll
   * @return die Dateiliste als JSON String
   * @throws IOException
   */
  public String liste(String fName, String ctxPath, String base/*, String path*/) throws IOException {
    File[] files = new File(base, fName).listFiles(new ImageFileFilter());
    if (files != null && files.length > 0) {
@@ -56,13 +65,13 @@
          datei.setTyp(Datei.TYP_DATEI);
        }
        String lowerName = dateiName.toLowerCase();
        if (lowerName.endsWith(Const.JPEG)
                || lowerName.endsWith(Const.JPG)
                || lowerName.endsWith(Const.PNG)) {
        if (lowerName.endsWith(ImageFileFilter.JPEG)
                || lowerName.endsWith(ImageFileFilter.JPG)
                || lowerName.endsWith(ImageFileFilter.PNG)) {
          datei.setBild(true);
          String ext = dateiName.substring(dateiName.lastIndexOf(STR_DOT));
          String ohneExt = dateiName.substring(0, dateiName.lastIndexOf(STR_DOT));
          datei.setMiniurl(ctxPath + /*"/" + */ fName + ohneExt + Const.TN + ext);
          datei.setMiniurl(ctxPath + /*"/" + */ fName + ohneExt + ImageFileFilter.TN + ext);
          //buildImgSrc(file, datei, ohneExt, ext);
        }
        liste.add(datei);
src/de/uhilger/fm/Mover.java
@@ -24,16 +24,34 @@
import java.nio.file.Path;
/**
 * Eine Klasse mit Methoden zum Kopieren und Verschieben von Dateien
 * Die Klasse Mover verschiebt und kopiert Dateien und Ordner
 *
 * Handhabung von Bilddateien:
 *
 * Fuer jede Datei mit Endung jpg, jpeg und png werden alle Varianten wie zum Beispiel
 * dateiname.jpg, dateiname_kl.jpg, dateiname_gr.jpg, dateiname_gr_b64.jpg usw.
 * beruecksichtigt.
 *
 * @author Ulrich Hilger, 15. Janaur 2024
 */
public class Mover extends FileHelper {
  public String copyOrMoveFiles(String fromPath, String toPath, String[] fileNames,
  public static final int OP_COPY = 1;
  public static final int OP_MOVE = 2;
  /**
   * Dateien und Ordner verschieben oder kopieren
   *
   * @param fromPath der Pfad zur Quelle  der Verschiebe- oder Kopieraktion
   * @param toPath der Pfad zum Ziel der Verschiebe- oder Kopieraktion
   * @param fileNames die Liste der Dateien und Ordner, die verschoben oder kopiert werden sollen
   * @param operation die gewuenschte Dateioperation, OP_COPY oder OP_MOVE
   * @param base der Basispfad, gegen den fromPath und toPath aufgeloest werden sollen
   * @throws IOException wenn etwas schief geht
   */
  public void copyOrMoveFiles(String fromPath, String toPath, String[] fileNames,
          int operation, String base) throws IOException {
    String result = null;
    //String result = null;
    File srcDir = new File(base, fromPath);
    File targetDir = new File(base, toPath);
    for (String fileName : fileNames) {
@@ -41,7 +59,7 @@
      //logger.fine("srcFile: " + srcFile);
      if (srcFile.isDirectory()) {
        //logger.fine("srcFile is directory.");
        CopyMoveVisitor bearbeiter = new CopyMoveVisitor();
        FileOpsVisitor bearbeiter = new FileOpsVisitor();
        bearbeiter.setTargetDir(targetDir.toPath());
        bearbeiter.setOperation(operation);
        Files.walkFileTree(srcFile.toPath(), bearbeiter);
@@ -51,12 +69,12 @@
        if (destFile.exists()) {
          destFile = getNewFileName(destFile);
        }
        if (operation == Const.OP_MOVE) {
        if (operation == OP_MOVE) {
          String fname = srcFile.getName().toLowerCase();
          if (fname.endsWith(Const.JPEG)
                  || fname.endsWith(Const.JPG)
                  || fname.endsWith(Const.PNG)) {
            moveImgFilesToDirectory(srcFile, srcDir, targetDir, false);
          if (fname.endsWith(ImageFileFilter.JPEG)
                  || fname.endsWith(ImageFileFilter.JPG)
                  || fname.endsWith(ImageFileFilter.PNG)) {
            moveImgFilesToDirectory(srcFile, srcDir, targetDir/*, false*/);
          } else {
            Files.move(source, destFile.toPath());
          }
@@ -65,11 +83,23 @@
        }
      }
    }
    return result;
    //return result;
  }
  private void moveImgFilesToDirectory(File srcFile, File srcDir, File targetDir,
          boolean createDestDir) throws IOException {
  /**
   * Eine Bilddatei mit allen Varianten verschieben oder kopieren
   *
   * Fuer jede Datei mit Endung jpg, jpeg und png werden alle Varianten wie zum Beispiel
   * dateiname.jpg, dateiname_kl.jpg, dateiname_gr.jpg, dateiname_gr_b64.jpg usw.
   * beruecksichtigt, also dateiname*.jpg.
   *
   * @param srcFile die Bilddatei, deren Varianten beruecksichtigt werden sollen
   * @param srcDir der Herkunftsort
   * @param targetDir der Zielort
   * @throws IOException wenn etwas schief geht
   */
  private void moveImgFilesToDirectory(File srcFile, File srcDir, File targetDir/*,
          boolean createDestDir*/) throws IOException {
    String fnameext = srcFile.getName();
    int dotpos = fnameext.lastIndexOf(".");
    String fname = fnameext.substring(0, dotpos);
src/de/uhilger/fm/Renamer.java
@@ -33,12 +33,12 @@
  
  public static final String STR_DOT = ".";
  
  public String umbenennen(HttpExchange exchange, String relPfad, String neuerName, File file) throws IOException {
  public String umbenennen(/*HttpExchange exchange, */String relPfad, String neuerName, File file)
          throws IOException {
    File neueDatei;
    //String relPfad = helper.getFileName(exchange);
    //File file = new File(exchange.getHttpContext().getAttributes().get(FileHandler.ATTR_FILE_BASE).toString(), relPfad);
    String fname = file.getName().toLowerCase();
    if(fname.endsWith(Const.JPEG) || fname.endsWith(Const.JPG) || fname.endsWith(Const.PNG)) {
    if(fname.endsWith(ImageFileFilter.JPEG) || fname.endsWith(ImageFileFilter.JPG) ||
            fname.endsWith(ImageFileFilter.PNG)) {
      neueDatei = renameImgFiles(file.getParentFile(), file, neuerName);  
    } else {
      neueDatei = new File(file.getParentFile(), neuerName);
@@ -63,21 +63,21 @@
    String ext = fnameext.substring(dotpos);
    //logger.fine("fname: " + fname + ", ext: " + ext);
    
    DirectoryStream<Path> stream = Files.newDirectoryStream(targetDir.toPath(), fname + "*" + ext); //"*.{txt,doc,pdf,ppt}"
    DirectoryStream<Path> stream = Files.newDirectoryStream(targetDir.toPath(), fname + "*" + ext);
    for (Path path : stream) {
      //logger.fine(path.getFileName().toString());
      alt = path.getFileName().toString();
      //logger.fine("alt: " + alt);
      if(alt.contains(Const.TN)) {
        neu = newfname + Const.TN + newext;
      } else if (alt.contains(Const.KL)) {
        neu = newfname + Const.KL + newext;
      } else if(alt.contains(Const.GR)) {
        neu = newfname + Const.GR + newext;
      } else if(alt.contains(Const.MT)) {
        neu = newfname + Const.MT + newext;
      } else if(alt.contains(Const.SM)) {
        neu = newfname + Const.SM + newext;
      if(alt.contains(ImageFileFilter.TN)) {
        neu = newfname + ImageFileFilter.TN + newext;
      } else if (alt.contains(ImageFileFilter.KL)) {
        neu = newfname + ImageFileFilter.KL + newext;
      } else if(alt.contains(ImageFileFilter.GR)) {
        neu = newfname + ImageFileFilter.GR + newext;
      } else if(alt.contains(ImageFileFilter.MT)) {
        neu = newfname + ImageFileFilter.MT + newext;
      } else if(alt.contains(ImageFileFilter.SM)) {
        neu = newfname + ImageFileFilter.SM + newext;
      } else {
        neu = newName;
      }
src/de/uhilger/fm/dateiliste-beispiel.json
New file
@@ -0,0 +1,27 @@
{
  "pfad": "/h2/cms/www/bilder/",
  "dateien": [{
      "name": ".DS_Store",
      "typ": "datei",
      "typKlasse": "icon-doc-inv",
      "bild": false
    }, {
      "name": "000022420019-d.jpg",
      "typ": "datei",
      "typKlasse": "icon-doc-inv",
      "bild": true,
      "miniurl": "/h2/cms/www/bilder/000022420019-d_tn.jpg"
    }, {
      "name": "000039350014-1920.jpg",
      "typ": "datei",
      "typKlasse": "icon-doc-inv",
      "bild": true,
      "miniurl": "/h2/cms/www/bilder/000039350014-1920_tn.jpg"
    }, {
      "name": "38036_006-029-1920-r.jpg",
      "typ": "datei",
      "typKlasse": "icon-doc-inv",
      "bild": true,
      "miniurl": "/h2/cms/www/bilder/38036_006-029-1920-r_tn.jpg"
    }]
}
src/de/uhilger/fm/package-info.java
@@ -1,4 +1,37 @@
/**
 * Klassen fuer das Dateimanagement.
 * Klassen fuer das Dateimanagement mit java.nio.file.
 *
 * Die folgenden Funktionen sind enthalten:
 *
 * <pre>
 * Ordnerinhalt auflisten:
 *    Lister().liste(ordnerName, ctx, basisOrdner)
 *
 *   TODO: JSON-Liste und Miniurl sowie Handhabung von Bilddateien ueberpruefen
 *
 * Datei speichern:
 *    Writer.speichern(file, content)
 *
 * Dateien und Ordner loeschen:
 *    Eraser.deleteFiles(relPfad, dateiname, basis)
 *
 * Kopieren von Dateien und Ordnern:
 *    Mover().copyOrMoveFiles(quelle, ziel, dateiNamen, op, base)
 *
 * Verschieben von Dateien und Ordnern:
 *    Mover().copyOrMoveFiles(quelle, ziel, dateiNamen, op, base)
 *
 * Duplizieren einer Datei:
 *    Duplicator().duplizieren(base, fileName)
 *
 * Umbenennen einer Datei oder eines Ordners:
 *    Renamer().umbenennen(exchange, fileName, params[1], file)
 *
 * Packen eines Ordners:
 *    Deflator().packFolder(fileName, path, base)
 *
 * Entpacken einer ZIP-Datei:
 *    Inflator().extractZipfile(fileName, path, base)
 * </pre>
 */
package de.uhilger.fm;