2011-02-01 16 views
16

Ho un programma che deve spostare un file da una directory a un'altra su un server FTP. Ad esempio, il file si trova in:Come posso usare FTP per spostare file tra le directory?

ftp://1.1.1.1/MAIN/Dir1 

e ho bisogno di spostare il file:

ftp://1.1.1.1/MAIN/Dir2 

ho trovato un paio di articoli che raccomandano l'uso del comando Rinomina, così ho provato quanto segue:

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(); 

Ma questo non sembra funzionare - ricevo il seguente errore:

The remote server returned an error: (550) File unavailable (e.g., file not found, no access).

In un primo momento ho pensato che questo potrebbe riguardare le autorizzazioni, ma per quanto posso vedere, ho le autorizzazioni per l'intero sito FTP (è sul mio PC locale e l'uri è risolto a localhost).

Dovrebbe essere possibile spostare file tra le directory come questa, e in caso contrario, come è possibile?

per affrontare alcuni dei punti di/suggerimenti che sono state sollevate:

  1. posso scaricare lo stesso file dalla directory di origine, quindi esiste sicuramente (quello che sto facendo è il download prima, e poi spostandolo da qualche altra parte).
  2. Posso accedere al sito ftp da un browser (sia la directory di origine che di destinazione)
  3. Il server ftp è in esecuzione con la mia istanza IIS sul mio computer locale.
  4. Il percorso e il caso sono corretti e non ci sono caratteri speciali.

Inoltre, ho provato a fissare il percorso della directory di essere:

ftp://1.1.1.1/%2fMAIN/Dir1/MyFile.txt 

Sia per il percorso di origine e di destinazione - ma questo non fa differenza neanche.

Ho trovato l'articolo this, che sembra dire che specificare la destinazione come percorso relativo potrebbe essere d'aiuto: non sembra possibile specificare un percorso assoluto come destinazione.

reqFTP.RenameTo = “../Dir2/MyFile.txt"; 
+1

Se si collega ftp://1.1.1/MAIN/Dir1/MyFile.txt in un browser, funziona? –

+0

Il percorso contiene caratteri speciali che devono essere sfuggiti? –

+0

Vedi le ultime modifiche, ma le risposte sono: sì - funziona da un browser e, no - il percorso non ha caratteri speciali –

risposta

10

MSDN sembra suggerire che il percorso sia considerato relativo e quindi tenta di accedere al server FTP utilizzando le credenziali fornite, quindi imposta la directory corrente nella directory <UserLoginDirectory>/path. Se questa non è la stessa directory in cui si trova il tuo file, riceverai un errore 550.

+0

Visualizza le ultime modifiche. Ho provato varie combinazioni di% 2f nel percorso ma senza successo –

+0

Ho aggiornato la domanda: sembra che tu avessi ragione, ma non sono riuscito a ottenere un percorso assoluto per lavorare, non importa quello che ho provato. –

+0

buona scoperta. Probabilmente mi ci sarebbe voluto un po 'per capire se fosse il mio problema. –

0

Avete queste cartelle definite nel servizio FTP? Il servizio FTP è in esecuzione? Se la risposta a entrambe le domande è no, non è possibile utilizzare FTP per spostare i file.

Provare ad aprire la cartella FTP in un client FTP e vedere cosa succede. Se avete ancora un errore, c'è qualcosa che non va con la tua definizione, come il servizio FTP non vede la cartella o la cartella non è logicamente in cui si pensa che è nel servizio FTP.

È anche possibile aprire il gestore IIS e osservare come sono configurate le cose in FTP.

Per quanto riguarda gli altri metodi per spostare i file, si può facilmente passare da un percorso UNC a un altro, fino a quando il conto del programma gira sotto dispone di autorizzazioni appropriate per entrambi. Il percorso UNC è simile a un percorso HTTP o FTP, con whacks nella direzione opposta e nessun protocollo specificato.

0

Il codice sembra corretto. Quindi o avete il percorso sbagliato, il file DOESNT esiste o dovete rispettare il caso (ovviamente Windows non è case sensitive, ma Linux, Unix lo sono).

Hai provato ad aprire il file in un browser? Apri Windows File Explorer e digita l'indirizzo nella barra del percorso e guarda cosa ottieni.

+0

Vedi le ultime modifiche - il file si apre bene in un browser –

1

sono stato in grado di ottenere questo lavoro, ma solo utilizzando il percorso come esiste sul server, vale a dire /DRIVELETTER:/FOLDERNAME/filename in renameTo = "

1

Cosa fare se avete solo percorsi assoluti?

Ok, mi è venuto attraverso questo post perché stavo ottenendo lo stesso errore.La risposta sembra essere quella di utilizzare un percorso relativo, che non è molto buono come soluzione al mio problema, perché ottengo i percorsi della cartella come stringhe di percorso assoluto.

soluzioni che ho escogitato al volo funzionano, ma sono a dir poco brutte: farò di questa una risposta wiki della comunità, e se ne ha una soluzione migliore, sentitevi liberi di modificare questo.

Da quando ho imparato questo ho 2 soluzioni.

  1. Prendere il percorso assoluto dallo spostamento al percorso e convertirlo in un URL relativo.

    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(); 
    } 
    

o ...

  1. Scarica il file dalla "ftp da" percorso, caricarlo sul "ftp a" percorso ed eliminarlo dal "ftp da" sentiero.

    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; 
    } 
    
16

avuto lo stesso problema e ha trovato un altro modo per risolvere il problema:

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; 

    } 
-2

sto lavorando al tipo identico di progetto, provare a costruire un servizio web in grado di spostare i file intorno e gira sul server dove sono i tuoi file. Costruiscilo con un parametro per passare il nome del file. Quando scrivi il file per iniziare potresti aggiungere un valore al nome del file, ad esempio il PK dei dati correlati al file, ecc.

+1

Questo dovrebbe essere un commento, non una risposta. –

+0

@ Jester610, puoi spiegare con un esempio. –

1

Nell'esempio di codice seguente ho provato con i seguenti dati e funziona.

La posizione di accesso FTP è "C: \ FTP".

Posizione file originale "C: \ FTP \ Data \ FTP.txt".

File da spostare, "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(); 
Problemi correlati