Comment puis-je utiliser FTP pour déplacer des fichiers entre répertoires?
j'ai un programme qui doit déplacer un fichier dans un autre répertoire sur un serveur FTP. Par exemple, le fichier se trouve dans:
ftp://1.1.1.1/MAIN/Dir1
et j'ai besoin de déplacer le fichier:
ftp://1.1.1.1/MAIN/Dir2
j'ai trouvé quelques articles recommandant L'utilisation de la commande Renommer, donc j'ai essayé ce qui suit:
Uri serverFile = new Uri(“ftp://1.1.1.1/MAIN/Dir1/MyFile.txt");
FtpWebRequest reqFTP= (FtpWebRequest)FtpWebRequest.Create(serverFile);
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUser, ftpPass);
reqFTP.RenameTo = “ftp://1.1.1.1/MAIN/Dir2/MyFile.txt";
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Mais cela ne semble pas fonctionner – j'obtiens l'erreur suivante:
le serveur distant a renvoyé une erreur: (550) fichier indisponible (e.g., fichier pas trouvé, pas d'accès).
au début j'ai pensé que cela pourrait se rapporter aux permissions, mais pour autant que je puisse voir, j'ai des permissions sur l'ensemble du site FTP (il est sur mon PC local et l'uri est résolu à localhost).
devrait-il être possible de déplacer des fichiers entre des répertoires comme celui-ci, et si ce n'est pas le cas, comment est-ce possible?
pour répondre À certains de le point / suggestions qui ont été soulevées:
- je peux télécharger le même fichier à partir du répertoire source, donc il existe définitivement (ce que je fais est de télécharger le fichier d'abord, puis de le déplacer ailleurs).
- je peux accéder au site ftp à partir d'un navigateur (à la fois la source et le répertoire cible)
- le serveur ftp tourne sous ma propre instance IIS sur ma machine locale.
- le chemin et le cas sont corrects et il n'y a pas de caractères spéciaux.
de plus, j'ai essayé de définir le chemin du répertoire être:
ftp://1.1.1.1/%2fMAIN/Dir1/MyFile.txt
à la fois pour le chemin source et le chemin cible - mais cela ne fait pas de différence non plus.
j'ai trouvé l'article, qui semble dire que la spécification de la destination avec un chemin relatif aiderait - il ne semble pas être possible de spécifier un chemin absolu comme destination.
reqFTP.RenameTo = “../Dir2/MyFile.txt";
9 réponses
MSDN semble suggérer que votre chemin est considéré comme relatif, et par conséquent il essaie de se connecter au serveur FTP en utilisant les informations de connexion fournies, puis définit le répertoire courant à <UserLoginDirectory>/path
répertoire. Si ce n'est pas le même répertoire que votre fichier, vous obtiendrez une erreur 550.
Eu le même problème et a trouvé une autre façon de résoudre le problème:
public string FtpRename( string source, string destination ) {
if ( source == destination )
return;
Uri uriSource = new Uri( this.Hostname + "/" + source ), UriKind.Absolute );
Uri uriDestination = new Uri( this.Hostname + "/" + destination ), UriKind.Absolute );
// Do the files exist?
if ( !FtpFileExists( uriSource.AbsolutePath ) ) {
throw ( new FileNotFoundException( string.Format( "Source '{0}' not found!", uriSource.AbsolutePath ) ) );
}
if ( FtpFileExists( uriDestination.AbsolutePath ) ) {
throw ( new ApplicationException( string.Format( "Target '{0}' already exists!", uriDestination.AbsolutePath ) ) );
}
Uri targetUriRelative = uriSource.MakeRelativeUri( uriDestination );
//perform rename
FtpWebRequest ftp = GetRequest( uriSource.AbsoluteUri );
ftp.Method = WebRequestMethods.Ftp.Rename;
ftp.RenameTo = Uri.UnescapeDataString( targetUriRelative.OriginalString );
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
return response.StatusDescription;
}
j'ai été capable de faire fonctionner ceci mais seulement en utilisant le chemin tel qu'il existe sur le serveur, c'est à dire /DRIVELETTER:/FOLDERNAME/filename
dans RenameTo = "
et si vous n'avez que des chemins absolus?
Ok, je suis tombé sur ce post parce que je recevais la même erreur. La réponse semble être d'utiliser un chemin relatif, ce qui n'est pas très bon comme solution à mon problème, parce que j'obtiens les chemins de dossiers comme des chaînes absolues de chemins.
Les solutions que j'ai trouvé à la volée, mais elles sont moche pour dire le moins. Je vais en faire une réponse wiki communautaire, et si quelqu'un a une meilleure solution, n'hésitez pas à éditer ceci.
Depuis que j'ai appris cela, j'ai 2 solutions.
prendre le chemin absolu du déplacement au chemin, et le convertir en une URL relative.
public static string GetRelativePath(string ftpBasePath, string ftpToPath) { if (!ftpBasePath.StartsWith("/")) { throw new Exception("Base path is not absolute"); } else { ftpBasePath = ftpBasePath.Substring(1); } if (ftpBasePath.EndsWith("/")) { ftpBasePath = ftpBasePath.Substring(0, ftpBasePath.Length - 1); } if (!ftpToPath.StartsWith("/")) { throw new Exception("Base path is not absolute"); } else { ftpToPath = ftpToPath.Substring(1); } if (ftpToPath.EndsWith("/")) { ftpToPath = ftpToPath.Substring(0, ftpToPath.Length - 1); } string[] arrBasePath = ftpBasePath.Split("/".ToCharArray()); string[] arrToPath = ftpToPath.Split("/".ToCharArray()); int basePathCount = arrBasePath.Count(); int levelChanged = basePathCount; for (int iIndex = 0; iIndex < basePathCount; iIndex++) { if (arrToPath.Count() > iIndex) { if (arrBasePath[iIndex] != arrToPath[iIndex]) { levelChanged = iIndex; break; } } } int HowManyBack = basePathCount - levelChanged; StringBuilder sb = new StringBuilder(); for (int i = 0; i < HowManyBack; i++) { sb.Append("../"); } for (int i = levelChanged; i < arrToPath.Count(); i++) { sb.Append(arrToPath[i]); sb.Append("/"); } return sb.ToString(); } public static string MoveFile(string ftpuri, string username, string password, string ftpfrompath, string ftptopath, string filename) { string retval = string.Empty; FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftpfrompath + filename); ftp.Method = WebRequestMethods.Ftp.Rename; ftp.Credentials = new NetworkCredential(username, password); ftp.UsePassive = true; ftp.RenameTo = GetRelativePath(ftpfrompath, ftptopath) + filename; Stream requestStream = ftp.GetRequestStream(); FtpWebResponse ftpresponse = (FtpWebResponse)ftp.GetResponse(); Stream responseStream = ftpresponse.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); return reader.ReadToEnd(); }
ou...
télécharger le fichier à partir du chemin" ftp from", Le télécharger sur le chemin" ftp to "et le supprimer du chemin" ftp from".
public static string SendFile(string ftpuri, string username, string password, string ftppath, string filename, byte[] datatosend) { if (ftppath.Substring(ftppath.Length - 1) != "/") { ftppath += "/"; } FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftppath + filename); ftp.Method = WebRequestMethods.Ftp.UploadFile; ftp.Credentials = new NetworkCredential(username, password); ftp.UsePassive = true; ftp.ContentLength = datatosend.Length; Stream requestStream = ftp.GetRequestStream(); requestStream.Write(datatosend, 0, datatosend.Length); requestStream.Close(); FtpWebResponse ftpresponse = (FtpWebResponse)ftp.GetResponse(); return ftpresponse.StatusDescription; } public static string DeleteFile(string ftpuri, string username, string password, string ftppath, string filename) { FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftppath + filename); ftp.Method = WebRequestMethods.Ftp.DeleteFile; ftp.Credentials = new NetworkCredential(username, password); ftp.UsePassive = true; FtpWebResponse response = (FtpWebResponse)ftp.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream); return reader.ReadToEnd(); } public static string MoveFile(string ftpuri, string username, string password, string ftpfrompath, string ftptopath, string filename) { string retval = string.Empty; byte[] filecontents = GetFile(ftpuri, username, password, ftpfrompath, filename); retval += SendFile(ftpuri, username, password, ftptopath, filename, filecontents); retval += DeleteFile(ftpuri, username, password, ftpfrompath, filename); return retval; }
dans l'exemple de code suivant j'ai essayé de suivre les données et cela fonctionne.
l'emplacement de connexion FTP est "C:\FTP".
emplacement du fichier original "C:\FTP\Data\FTP.txt".
fichier à déplacer, "C:\FTP\Move\FTP.txt".
Uri serverFile = new Uri(“ftp://localhost/Data/FTP.txt");
FtpWebRequest reqFTP= (FtpWebRequest)FtpWebRequest.Create(serverFile);
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.Credentials = new NetworkCredential(ftpUser, ftpPass);
reqFTP.RenameTo = “../Move/FTP.txt";
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
avez-vous ces dossiers définis dans le service FTP? Est le service FTP en cours d'exécution? Si la réponse à l'une ou l'autre de ces questions est non, vous ne pouvez pas utiliser FTP pour déplacer les fichiers.
essayez d'ouvrir le dossier FTP d'un client FTP et voyez ce qui se passe. Si vous avez toujours une erreur, il y a quelque chose qui ne va pas avec votre définition car le service FTP ne voit pas le dossier ou le dossier n'est pas logiquement où vous pensez qu'il est dans le service FTP.
vous pouvez également ouvrir le gestionnaire de L'IIS et regardez comment les choses sont configurées dans FTP.
comme pour les autres méthodes pour déplacer des fichiers, vous pouvez facilement passer d'un chemin UNC à un autre, aussi longtemps que le compte sous lequel le programme s'exécute a les permissions appropriées aux deux. Le chemin UNC est similaire à un chemin HTTP ou FTP, avec des coups dans la direction opposée et sans protocole spécifié.
le code semble correct. Donc soit vous avez le mauvais chemin, le fichier n'existe pas ou vous devez respecter case (évidemment Windows N'est pas sensible à la casse, mais Linux, Unix le sont).
Avez-vous essayer d'ouvrir le fichier dans un navigateur? Ouvrez L'Explorateur de fichiers Windows et tapez l'adresse dans la barre d'accès et voyez ce que vous obtenez.
U peut utiliser ce code:
Fichier emplacement d'origine "ftp://example.com/directory1/Somefile.file".
le Fichier à déplacer, "/newDirectory/Somefile.fichier."
notez que l'Url de destination n'a pas besoin de commencer par:ftp://example.com
NetworkCredential User = new NetworkCredential("UserName", "password");
FtpWebRequest Wr =FtpWebRequest)FtpWebRequest.Create("ftp://Somwhere.com/somedirectory/Somefile.file");
Wr.UseBinary = true;
Wr.Method = WebRequestMethods.Ftp.Rename;
Wr.Credentials = User;
Wr.RenameTo = "/someotherDirectory/Somefile.file";
back = (FtpWebResponse)Wr.GetResponse();
bool Success = back.StatusCode == FtpStatusCode.CommandOK || back.StatusCode == FtpStatusCode.FileActionOK;
je travaille sur le même type de projet, essayez de construire un service web qui peut déplacer les fichiers et tourne sur le serveur où vos fichiers sont. Construire avec un paramètre à passer dans le nom de fichier. Lors de l'écriture du fichier pour commencer par vous pourriez vouloir ajouter une valeur au nom du fichier, dire le PK des données qui correspond au fichier etc.