Skip to content
Snippets Groups Projects
Commit 9a8a58f6 authored by fabiovandewaeter's avatar fabiovandewaeter
Browse files

tp2 download fichiers et dossiers

parent 1e4e7f1f
Branches
Tags
No related merge requests found
......@@ -72,7 +72,9 @@ Puis ouvrir le fichier `target/site/apidocs/index.html`
## Fonctionnalités
`python3 serveur_ftp.py` anonymous/anonymous ou user/password
En utilisant la commande suivante `python3 serveur_ftp.py`, vous pouvez donner les identifiants FTP anonymous/anonymous ou user/password
Il faut aussi penser à ajouter un serveur FTP avec la commande suivant : `curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer valid-token-1" -d '{"alias":"mon-ftp","host":"localhost","port":2121}' http://localhost:8080/ftps`
**Note < 10 si le code fourni ne compile pas et ne peut pas être exécuté en suivant les instructions:**
......@@ -90,14 +92,14 @@ curl -X GET -H "Authorization: Bearer valid-token-1" -H "X-FTP-User: anonymous"
- download fichier :
```shell
curl -X GET -H "Authorization: Bearer valid-token-1" http://localhost:8080/ftps/mon-ftp/test
curl -X GET -H "Authorization: Bearer valid-token-1" -H "X-FTP-User: anonymous" -H "X-FTP-Pass: anonymous" http://localhost:8080/ftps/mon-ftp/fichier1 -o fichier1
```
-download dossier :
```shell
curl -X GET -H "Authorization: Bearer valid-token-1" -H "X-FTP-User: user" -H "X-FTP-Pass: password" http://localhost:8080/ftps/mon-ftp/dir4 -o test.zip
curl -X GET -H "Authorization: Bearer valid-token-1" -H "X-FTP-User: anonymous" -H "X-FTP-Pass: anonymous" http://localhost:8080/ftps/mon-ftp/dossier1 -o dossier1.zip
unzip test.zip
unzip dossier1.zip
```
- upload fichier :
......
......@@ -11,7 +11,6 @@ import java.util.List;
public class FTPResource {
private FTPService ftpService;
// Endpoints pour gérer la configuration des serveurs FTP
public FTPResource(FTPService ftpService) {
this.ftpService = ftpService;
......@@ -29,6 +28,8 @@ public class FTPResource {
return Response.ok(servers).build();
}
// --- Endpoints pour gérer la configuration des serveurs FTP ---
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addFTPServer(FTPServerConfig config, @Context UriInfo uriInfo) {
......@@ -104,10 +105,10 @@ public class FTPResource {
}
}
// GET pour récupérer la structure d'un répertoire ou d'un fichier
// GET pour télécharger une ressource : fichier ou dossier compressé en ZIP
@GET
@Path("/{alias}/{path: .+}")
@Produces(MediaType.APPLICATION_JSON)
public Response getFTPResource(
@PathParam("alias") String alias,
@PathParam("path") String path,
......@@ -115,8 +116,23 @@ public class FTPResource {
@HeaderParam("X-FTP-Pass") String pass) {
System.out.println("getFTPResource()");
try {
FTPService.FtpNode root = ftpService.getResourceTree(alias, path, user, pass);
return Response.ok(root).build();
FTPService.FtpNode node = ftpService.getResourceTree(alias, path, user, pass);
if (node.isDirectory) {
System.out.println("getFTPResource() > directory");
byte[] zipData = ftpService.downloadDirectoryAsZip(alias, path, user, pass);
return Response.ok(zipData)
.header("Content-Type", "application/zip")
.header("Content-Disposition", "attachment; filename=\"" + getFileName(path) + ".zip\"")
.build();
} else {
System.out.println("getFTPResource() > NOT directory");
byte[] fileData = ftpService.downloadFile(alias, path, user, pass);
String contentType = determineContentType(path);
return Response.ok(fileData)
.header("Content-Type", contentType)
.header("Content-Disposition", "attachment; filename=\"" + getFileName(path) + "\"")
.build();
}
} catch (FTPException e) {
return Response.status(e.getStatus()).entity(e.getMessage()).build();
} catch (IOException e) {
......@@ -207,4 +223,21 @@ public class FTPResource {
return Response.serverError().entity("Erreur FTP : " + e.getMessage()).build();
}
}
// Méthode utilitaire pour extraire le nom de la ressource à partir du chemin
private String getFileName(String path) {
return path.substring(path.lastIndexOf('/') + 1);
}
// Méthode pour déterminer le type de contenu en fonction de l'extension
private String determineContentType(String path) {
if (path.endsWith(".txt"))
return "text/plain";
if (path.endsWith(".html"))
return "text/html";
if (path.endsWith(".json"))
return "application/json";
// Par défaut, renvoie binaire
return "application/octet-stream";
}
}
......@@ -5,7 +5,6 @@ import org.apache.commons.net.ftp.FTPFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
......@@ -22,21 +21,33 @@ public class FTPService {
}
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// Normaliser le chemin en retirant le slash final s'il y en a un
// Normaliser le chemin : retirer le slash final s'il y en a un
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
FTPFile[] files = ftpClient.listFiles(path);
if (files == null || files.length == 0) {
throw new FTPException("Ressource non trouvée : " + path, 404);
// Vérifier si c'est un dossier
boolean isDir = ftpClient.changeWorkingDirectory(path);
if (isDir) {
// Même si le dossier est vide, c'est valide
return buildFtpTree(ftpClient, path);
} else {
// Sinon, tenter de récupérer un flux de fichier
InputStream is = ftpClient.retrieveFileStream(path);
if (is != null) {
is.close();
ftpClient.completePendingCommand();
return new FtpNode(getFileName(path), false);
} else {
throw new FTPException("Ressource non trouvée : " + path, 404);
}
}
return buildFtpTree(ftpClient, path);
} finally {
FTPClientFactory.disconnect(ftpClient);
}
}
// Méthode récursive pour construire l'arborescence
private FtpNode buildFtpTree(FTPClient ftpClient, String path) throws IOException {
FTPFile[] files = ftpClient.listFiles(path);
FtpNode node = new FtpNode(getFileName(path), true);
......@@ -53,6 +64,82 @@ public class FTPService {
return node;
}
public byte[] downloadFile(String alias, String path, String user, String pass)
throws IOException, FTPException {
FTPClient ftp = FTPClientFactory.createClient(alias);
try {
if (!ftp.login(user, pass)) {
throw new FTPException("Authentification FTP échouée", 401);
}
ftp.enterLocalPassiveMode();
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = ftp.retrieveFileStream(path);
if (is == null) {
throw new FTPException("Ressource non trouvée : " + path, 404);
}
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
is.close();
ftp.completePendingCommand();
return baos.toByteArray();
} finally {
FTPClientFactory.disconnect(ftp);
}
}
public byte[] downloadDirectoryAsZip(String alias, String path, String user, String pass)
throws IOException, FTPException {
FTPClient ftp = FTPClientFactory.createClient(alias);
try {
if (!ftp.login(user, pass)) {
throw new FTPException("Authentification FTP échouée", 401);
}
ftp.enterLocalPassiveMode();
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
addDirectoryToZip(ftp, path, "", zos);
zos.close();
return baos.toByteArray();
} finally {
FTPClientFactory.disconnect(ftp);
}
}
private void addDirectoryToZip(FTPClient ftp, String remotePath, String basePath, ZipOutputStream zos)
throws IOException {
FTPFile[] files = ftp.listFiles(remotePath);
if (files == null || files.length == 0) {
return;
}
for (FTPFile file : files) {
String filePath = remotePath + "/" + file.getName();
String zipEntryPath = basePath.isEmpty() ? file.getName() : basePath + "/" + file.getName();
if (file.isDirectory()) {
zos.putNextEntry(new ZipEntry(zipEntryPath + "/"));
zos.closeEntry();
addDirectoryToZip(ftp, filePath, zipEntryPath, zos);
} else {
zos.putNextEntry(new ZipEntry(zipEntryPath));
InputStream is = ftp.retrieveFileStream(filePath);
if (is != null) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
is.close();
ftp.completePendingCommand();
}
zos.closeEntry();
}
}
}
public void uploadFile(String alias, String path, String user, String pass, InputStream fileStream)
throws IOException, FTPException {
FTPClient ftp = FTPClientFactory.createClient(alias);
......@@ -95,7 +182,8 @@ public class FTPService {
}
}
public void deleteResource(String alias, String path, String user, String pass) throws IOException, FTPException {
public void deleteResource(String alias, String path, String user, String pass)
throws IOException, FTPException {
FTPClient ftp = FTPClientFactory.createClient(alias);
try {
if (!ftp.login(user, pass)) {
......@@ -111,7 +199,6 @@ public class FTPService {
}
}
// Méthode récursive de suppression
private boolean deleteRecursive(FTPClient ftp, String path) throws IOException {
if (ftp.deleteFile(path)) {
return true;
......@@ -152,7 +239,6 @@ public class FTPService {
}
}
// Méthode utilitaire pour extraire le nom du fichier/dossier à partir du chemin
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