2013-03-19 16 views
5

Ho problemi di gestione dei file in un FTP quando hanno caratteri speciali. Ad esempio nomi di file con ó o simili.Caratteri speciali nei file FTP

Ti faccio un esempio. Prima di tutto voglio elencare ed elaborare ogni file di una cartella nel FTP:

ftp = CType(FtpWebRequest.Create(sFtpPath), FtpWebRequest) 
ftp.Method = WebRequestMethods.Ftp.ListDirectory 
reader = New StreamReader(ftp.GetResponse().GetResponseStream()) 

files = reader.ReadToEnd.Split(New String() {NewLine}, StringSplitOptions.RemoveEmptyEntries) 
reader.Close() 

Ma questo mi sta dando problemi quando il file contiene caratteri speciali perché la stringa che ho per il file non "esiste" su FTP, ad esempio:

For Each sFich As String In files 
    ftp = CType(FtpWebRequest.Create(sFtpPath & "/" & sFich), FtpWebRequest) 
    ftp.Method = WebRequestMethods.Ftp.DownloadFile 
    reader = New StreamReader(ftp.GetResponse().GetResponseStream()) 

    '... 
Next 

ad esempio, il file EXAMPLE_aró sul FTP, qui viene recuperato come EXAMPLE_ar□, in modo che quando provo a scaricare il file si dice che doesnt esiste.

Come posso gestirlo?

risposta

2

A giudicare dalle risposte a this question, potrebbe essere necessario specificare la codifica del StreamReader che si sta utilizzando per ottenere la lista dei file. L'impostazione predefinita è UTF8, è possibile utilizzare altre codifiche in questo modo:

reader = New StreamReader(ftp.GetResponse().GetResponseStream(), System.Text.Encoding.Unicode) 

Quando mi imbatto in problemi di codifica, di solito copiare e incollare la stringa confusa in un editor in grado di mostrare i valori esadecimali per i personaggi, e poi capire la codifica da lì.

La stringa sopra riportata contiene il carattere 00F3. Il tuo profilo dice che sei in Spagna. Mettere quei due insieme, con l'aiuto di Google sto indovinando il server FTP utilizza il sapore spagnolo di EBCDIC, che è il codice delle pagine 1145. Quindi provare questo:

reader = New StreamReader(ftp.GetResponse().GetResponseStream(), System.Text.Encoding.GetEncoding(1145)) 

Edit: Risulta F3 è l'o acuta nella maggior parte delle codifiche, incluso ASCII esteso, l'EBCDIC è appena entrato nella mia ricerca.

+0

Non ha funzionato. Invece di avere una lista di nomi di file ottengo una sola stringa in 'reader.ReadToEnd' che non posso dividere e tutti i caratteri non sono validi (tutti i quadrati illeggibili). Quando sono aperti in un editor appropriato, in unicode sono tutti caratteri cinesi e con la codifica "1145" sono tutti caratteri strani come 'ÃÁÊÈ/ëÍ' – SysDragon

+0

Hai provato ASCII? – Matt

+0

Quale 'ASCII' elenca i file ma mette un'? 'Dove dovrebbero essere i caratteri speciali. – SysDragon

0

Ho provato a utilizzare alcuni caratteri speciali e il sotto funziona bene per me. La funzione listdir crea la lista ... Forse si può provare e farci sapere ...

Public Shared Function DownloadFileFromServer(fileUri As Uri) As Boolean 

    If fileUri.Scheme <> Uri.UriSchemeFtp Then 
     Return False 
    End If 
    ' Get the object used to communicate with the server. 
    Dim request As New WebClient() 


    request.Credentials = New NetworkCredential("user", "pass") 
    Try 
     Dim newFileData As Byte() = request.DownloadData(fileUri.ToString()) 
     Dim fileString As String = System.Text.Encoding.UTF8.GetString(newFileData) 
     'do something with data 
     Console.WriteLine(fileString) 
    Catch e As WebException 
     Console.WriteLine(e.ToString()) 
    End Try 
    Return True 
End Function 

Public Shared Function listDir() As Boolean 

    Dim request As FtpWebRequest = DirectCast(WebRequest.Create("ftp://www.yourftpsite.com/docs/"), FtpWebRequest) 
    request.Method = WebRequestMethods.Ftp.ListDirectoryDetails 

    request.Credentials = New NetworkCredential("user", "pass") 

    Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse) 

    Dim responseStream As Stream = response.GetResponseStream() 
    Dim reader As New StreamReader(responseStream) 

    Dim dirlist As String() = Nothing 
    dirlist = reader.ReadToEnd().Split(New String() {vbCr & vbLf}, StringSplitOptions.RemoveEmptyEntries) 

    For Each dirLine As String In dirlist 

     Dim dirData As String = dirLine 

     ' Parse date 
     Dim lineDate As String = dirData.Substring(0, 17) 
     Dim dateTime__1 As DateTime = DateTime.Parse(lineDate) 
     dirData = dirData.Remove(0, 24) 

     ' check if line is a directory 
     Dim dir As String = dirData.Substring(0, 5) 
     Dim isDirectory As Boolean = dir.Equals("<dir>", StringComparison.InvariantCultureIgnoreCase) 
     dirData = dirData.Remove(0, 5) 
     dirData = dirData.Remove(0, 10) 

     ' get the filename 
     If Not isDirectory Then 
      Dim fileName As String = dirData 

      'the actual filename 
      Console.WriteLine("name= " & fileName) 

     End If 
    Next 

    reader.Close() 
    response.Close() 

    Return True 

End Function 
+0

provato il codice e ancora mi dà l'illeggibile caratteri. 'ListDirectoryDetails' funziona come' ListDirectory' per il recupero dei nomi dei file. – SysDragon

0

Nel mio caso, il codice sembrava funzionare bene con caratteri latini accentati - non era una codifica di caratteri latini tanto quanto era il simbolo # hash/numero.

La risposta è arrivata da Gary Yang (Microsoft Online Community Support). La chiave era usare Uri.EscapeDataString(). La sua risposta non ha funzionato, ma per rispetto è qui sotto:

Ti suggerisco di provare a codificare il percorso del file. Si prega di fare riferimento al seguente codice:

string FTPFilePath = "ftp://myserverip.com/Beatles #1 Hits/Help document.mp3"; 
if ((FTPFilePath).IndexOf("#") > -1){ 
targetUri = new Uri(Uri.EscapeDataString(FTPFilePath)); 
} 
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(targetUri); 

Ecco la mia versione di lavoro:

Dim ftpFilePath = "ftp://myserverip.com/Beatles #1 Hits/Help document.mp3" 

Dim parsedUri = new Uri(ftpFilePath) 
Dim scheme = parsedUri.Scheme 
Dim host = parsedUri.Host 
Dim port = parsedUri.Port 
Dim pathThatMightHaveHashSigns = ftpFilePath.Replace(String.Format("{0}://{1}", scheme, host), String.Empty) 

'Dim targetUri = new Uri(Uri.EscapeDataString(ftpFilePath)) 
' The above line would throw a UriFormatException "Invalid URI: The format of the URI could not be determined." 

Dim targetUri = new UriBuilder(scheme, host, port, pathThatMightHaveHashSigns).Uri 
Dim request = CType(WebRequest.Create(targetUri), FtpWebRequest) 

... e per C#:

var ftpFilePath = "ftp://myserverip.com/Beatles #1 Hits/Help document.mp3"; 

var parsedUri = new Uri(ftpFilePath); 
var scheme = parsedUri.Scheme; 
var host = parsedUri.Host; 
var port = parsedUri.Port; 
var pathThatMightHaveHashSigns = ftpFilePath.Replace(String.Format("{0}://{1}", scheme, host), String.Empty); 

//var targetUri = new Uri(Uri.EscapeDataString(ftpFilePath)); 
// The above line would throw a UriFormatException "Invalid URI: The format of the URI could not be determined." 

var targetUri = new UriBuilder(scheme, host, port, pathThatMightHaveHashSigns).Uri; 
targetUri.Dump(); 
+0

Oh, ho anche capito che ho ftpRequest.UseBinary = true; impostato in modo forse che significa che non devo specificare le codifiche stringa? – Colin