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

correction download dossiers

parent 2407e888
No related branches found
No related tags found
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