Skip to content
Snippets Groups Projects
Commit d5fbc88b authored by Fabio Vandewaeter's avatar Fabio Vandewaeter
Browse files

correction download dossiers

parent 2407e888
Branches
Tags
No related merge requests found
......@@ -3,10 +3,14 @@ package fil.sr2.flopbox;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
......@@ -15,6 +19,7 @@ import org.apache.commons.net.ftp.FTPFile;
@Path("/ftps")
public class FTPResource {
// ======== FTP Servers ========
// GET /ftps - liste des serveurs FTP enregistrés
@GET
@Produces(MediaType.APPLICATION_JSON)
......@@ -24,18 +29,48 @@ public class FTPResource {
return Response.ok(servers).build();
}
// returns the content of the directory as an array it is a directory OR the
// content of the file
// POST /ftps - enregistre un nouveau serveur FTP
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addFTPServer(FTPServerConfig config, @Context UriInfo uriInfo) {
System.out.println("addFTPServer()");
boolean created = FTPServerRepository.getInstance().addServer(config);
if (!created) {
return Response.status(Response.Status.CONFLICT).entity("Alias déjà utilisé").build();
}
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(config.getAlias());
return Response.created(builder.build()).build();
}
@DELETE
@Path("/{alias}")
public Response removeFTPServer(@PathParam("alias") String alias) {
System.out.println("removeFTPServer()");
boolean removed = FTPServerRepository.getInstance().removeServer(alias);
return removed ? Response.noContent().build() : Response.status(Response.Status.NOT_FOUND).build();
}
@PUT
@Path("/{alias}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateFTPServer(@PathParam("alias") String alias, FTPServerConfig newConfig) {
System.out.println("updateFTPServer()");
boolean updated = FTPServerRepository.getInstance().updateServer(alias, newConfig);
return updated ? Response.ok(newConfig).build() : Response.status(Response.Status.NOT_FOUND).build();
}
// =============================
// ========= Resources =========
@GET
@Path("/{alias}/{path: .+}")
@Produces(MediaType.APPLICATION_JSON)
@Produces({ MediaType.APPLICATION_OCTET_STREAM, "application/zip" })
public Response getFTPResource(
@PathParam("alias") String alias,
@PathParam("path") String path,
@HeaderParam("X-FTP-User") String user,
@HeaderParam("X-FTP-Pass") String pass) {
System.out.println("GetFTPResource()");
FTPServerConfig config = FTPServerRepository.getInstance().getServer(alias);
if (config == null) {
return Response.status(Response.Status.NOT_FOUND)
......@@ -50,42 +85,161 @@ public class FTPResource {
}
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// Normaliser le chemin en retirant le slash final
// Normaliser le chemin
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
// Vérifier si le chemin est un répertoire
// Vérifier si c'est un dossier
boolean isDirectory = ftpClient.changeWorkingDirectory(path);
if (isDirectory) {
String currentDirectory = ftpClient.printWorkingDirectory();
System.out.println("Répertoire courant : " + currentDirectory);
// Créer un ZIP du dossier
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
addDirectoryToZip(ftpClient, currentDirectory, "", zos);
zos.close();
return Response.ok(baos.toByteArray())
.type("application/zip")
.header("Content-Disposition", "attachment; filename=\"" + getFileName(path) + ".zip\"")
.build();
} else {
// Télécharger le fichier
InputStream is = ftpClient.retrieveFileStream(path);
if (is != null) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
is.close();
ftpClient.completePendingCommand();
return Response.ok(outputStream.toByteArray())
.type(determineContentType(path))
.header("Content-Disposition", "attachment; filename=\"" + getFileName(path) + "\"")
.build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("Ressource non trouvée").build();
}
}
} catch (IOException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur FTP: " + e.getMessage()).build();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String determineContentType(String path) {
if (path.endsWith(".txt"))
return MediaType.TEXT_PLAIN;
if (path.endsWith(".html"))
return MediaType.TEXT_HTML;
if (path.endsWith(".json"))
return MediaType.APPLICATION_JSON;
return MediaType.APPLICATION_OCTET_STREAM;
}
private void addDirectoryToZip(FTPClient ftpClient, String remotePath, String basePath, ZipOutputStream zos)
throws IOException {
FTPFile[] files = ftpClient.listFiles(remotePath);
if (files == null || files.length == 0) {
System.out.println("Aucun fichier trouvé dans le dossier : " + remotePath);
return;
}
for (FTPFile file : files) {
String filePath = remotePath.isEmpty() ? file.getName() : remotePath + "/" + file.getName();
String zipEntryPath = basePath.isEmpty() ? file.getName() : basePath + "/" + file.getName();
if (file.isDirectory()) {
// Ajouter une entrée de dossier au ZIP
zos.putNextEntry(new ZipEntry(zipEntryPath + "/"));
zos.closeEntry();
// Explorer le sous-dossier récursivement
addDirectoryToZip(ftpClient, filePath, zipEntryPath, zos);
} else {
// Ajouter un fichier au ZIP
ZipEntry entry = new ZipEntry(zipEntryPath);
zos.putNextEntry(entry);
InputStream is = ftpClient.retrieveFileStream(filePath);
if (is == null) {
System.out.println("Impossible de lire le fichier : " + filePath);
continue;
}
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
is.close();
ftpClient.completePendingCommand(); // Important pour finaliser la lecture
zos.closeEntry();
}
}
}
@GET
@Path("/list/{alias}/{path: .+}")
@Produces(MediaType.APPLICATION_JSON)
public Response listDirectory(
@PathParam("alias") String alias,
@PathParam("path") String path,
@HeaderParam("X-FTP-User") String user,
@HeaderParam("X-FTP-Pass") String pass) {
FTPServerConfig config = FTPServerRepository.getInstance().getServer(alias);
if (config == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity("Serveur FTP non trouvé").build();
}
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(config.getHost(), config.getPort());
if (!ftpClient.login(user, pass)) {
return Response.status(Response.Status.UNAUTHORIZED)
.entity("Authentification FTP échouée").build();
}
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
FTPFile[] files = ftpClient.listFiles(path);
if (files == null || files.length == 0) {
return Response.status(Response.Status.NOT_FOUND)
.entity("Ressource non trouvée : " + path).build();
.entity("Ressource non trouvée: " + path).build();
}
// Construire la structure JSON
FtpNode root = buildFtpTree(ftpClient, path);
ftpClient.logout();
ftpClient.disconnect();
return Response.ok(root).build();
} catch (IOException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur FTP : " + e.getMessage()).build();
}
}
// Fonction récursive pour construire l'arborescence FTP
private FtpNode buildFtpTree(FTPClient ftpClient, String path) throws IOException {
FTPFile[] files = ftpClient.listFiles(path);
FtpNode node = new FtpNode(getFileName(path), true); // Root est un dossier
if (files != null) {
for (FTPFile file : files) {
String fullPath = path + "/" + file.getName();
if (file.isDirectory()) {
node.children.add(buildFtpTree(ftpClient, fullPath)); // Récursif pour les dossiers
} else {
node.children.add(new FtpNode(file.getName(), false)); // Ajouter fichier
.entity("Erreur FTP: " + e.getMessage()).build();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return node;
}
// Classe représentant un nœud JSON (fichier ou dossier)
......@@ -103,35 +257,21 @@ public class FTPResource {
}
}
// POST /ftps - enregistre un nouveau serveur FTP
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addFTPServer(FTPServerConfig config, @Context UriInfo uriInfo) {
System.out.println("addFTPServer()");
boolean created = FTPServerRepository.getInstance().addServer(config);
if (!created) {
return Response.status(Response.Status.CONFLICT).entity("Alias déjà utilisé").build();
// Fonction récursive pour construire l'arborescence FTP
private FtpNode buildFtpTree(FTPClient ftpClient, String path) throws IOException {
FTPFile[] files = ftpClient.listFiles(path);
FtpNode node = new FtpNode(getFileName(path), true); // Root est un dossier
if (files != null) {
for (FTPFile file : files) {
String fullPath = path + "/" + file.getName();
if (file.isDirectory()) {
node.children.add(buildFtpTree(ftpClient, fullPath)); // Récursif pour les dossiers
} else {
node.children.add(new FtpNode(file.getName(), false)); // Ajouter fichier
}
}
}
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(config.getAlias());
return Response.created(builder.build()).build();
}
@DELETE
@Path("/{alias}")
public Response removeFTPServer(@PathParam("alias") String alias) {
System.out.println("removeFTPServer()");
boolean removed = FTPServerRepository.getInstance().removeServer(alias);
return removed ? Response.noContent().build() : Response.status(Response.Status.NOT_FOUND).build();
}
@PUT
@Path("/{alias}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateFTPServer(@PathParam("alias") String alias, FTPServerConfig newConfig) {
System.out.println("updateFTPServer()");
boolean updated = FTPServerRepository.getInstance().updateServer(alias, newConfig);
return updated ? Response.ok(newConfig).build() : Response.status(Response.Status.NOT_FOUND).build();
return node;
}
@PUT
......@@ -142,18 +282,45 @@ public class FTPResource {
@PathParam("path") String path,
@HeaderParam("X-FTP-User") String user,
@HeaderParam("X-FTP-Pass") String pass,
@HeaderParam("X-Zip-Extract") Boolean extractZip,
InputStream fileStream) {
System.out.println("uploadFile()");
FTPServerConfig config = FTPServerRepository.getInstance().getServer(alias);
if (config == null) {
return Response.status(Response.Status.NOT_FOUND).entity("Serveur non trouvé").build();
}
FTPClient ftp = new FTPClient();
try {
ftp.connect(config.getHost(), config.getPort());
ftp.login(user, pass);
boolean success = ftp.storeFile(path, fileStream);
return success ? Response.ok().build() : Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
ftp.enterLocalPassiveMode();
ftp.setFileType(FTP.BINARY_FILE_TYPE);
if (extractZip != null && extractZip) {
if (!ftp.changeWorkingDirectory(path)) {
return Response.status(400).entity("Le chemin n'est pas un dossier").build();
}
ZipInputStream zis = new ZipInputStream(fileStream);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
String fullPath = path + "/" + entry.getName();
if (entry.isDirectory()) {
createDirectories(ftp, fullPath);
} else {
String parentDir = fullPath.substring(0, fullPath.lastIndexOf('/'));
createDirectories(ftp, parentDir);
ftp.storeFile(fullPath, zis);
}
zis.closeEntry();
}
zis.close();
return Response.ok().build();
} else {
boolean success = ftp.storeFile(path, fileStream);
return success ? Response.ok().build() : Response.status(500).entity("Erreur d'upload").build();
}
} catch (IOException e) {
return Response.serverError().entity(e.getMessage()).build();
return Response.serverError().entity("Erreur FTP: " + e.getMessage()).build();
} finally {
try {
if (ftp.isConnected()) {
......@@ -166,6 +333,21 @@ public class FTPResource {
}
}
private void createDirectories(FTPClient ftp, String path) throws IOException {
String[] dirs = path.split("/");
StringBuilder sb = new StringBuilder();
for (String dir : dirs) {
if (dir.isEmpty())
continue;
sb.append("/").append(dir);
String currentDir = sb.toString();
if (!ftp.changeWorkingDirectory(currentDir)) {
ftp.makeDirectory(currentDir);
ftp.changeWorkingDirectory(currentDir);
}
}
}
@POST
@Path("/{alias}/{path: .+}")
@Consumes({ MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN })
......@@ -310,4 +492,5 @@ public class FTPResource {
private String getFileName(String path) {
return path.substring(path.lastIndexOf('/') + 1);
}
// =============================
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment