3 回答
Judging from the answers to this question, you may need to specify the encoding of the StreamReader
you're using to get the file listing. The default is UTF8, you can use other encodings like so:
reader = New StreamReader(ftp.GetResponse().GetResponseStream(), System.Text.Encoding.Unicode)
When I run into encoding issues, I usually copy and paste the garbled string into an editor that can show the hex values for the characters, and then figure out the encoding from there.
The string you have above contains the character 00F3. Your profile says you are in Spain. Putting those two together, with the help of Google I am guessing the FTP server is using the Spanish flavor of EBCDIC, which is code page 1145. So try this:
reader = New StreamReader(ftp.GetResponse().GetResponseStream(), System.Text.Encoding.GetEncoding(1145))
Edit: Turns out F3 is the acute o in most encodings, including extended ASCII, the EBCDIC one just came up in my search.
I have tried using some special characters and the below works well for me. The listDir function creates the list... Maybe you can try and let us know...
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
In my case, the code seemed to work fine with accented Latin characters - it wasn't an encoding of Latin characters so much as it was the # hash/number symbol.
The answer to that came from Gary Yang (Microsoft Online Community Support). The key was to use Uri.EscapeDataString(). His answer didn't work, but out of respect it is below:
I suggest you try to encode the file path. Please refer to the following code:
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);
Here's my working version:
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)
... and for 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();