首先,这是我硬盘上的原始文件名:שקל100.jpg שקל是希伯来语中的一个词 当我将文件上传到我的ftp时,上传没有问题,但ftp服务器上的文件名如下:
ftp服务器上的文件看起来像gibrish而不是希伯来语。 问题是我正在尝试下载文件。文件名是100 ??? .jpg 并且FtpWebrequest不知道什么是100 ??? jpg
reqFTP = (FtpWebRequest)FtpWebRequest.Create(fileurl);
在fileurl中,我看到:ftp://ftp.newsxpressmedia.com/D/100???.jpg
问题是在这种情况下我该怎么办?也许强制将文件名重新命名为某个默认的临时文件名?
我想问题是ftp服务器ipage.com主机不知道读取希伯来文,所以上传后看起来像gibrish。
或许我需要以某种方式上传它使用希伯来语编码文件名? 这是我用来上传文件的方法:
private void StringArrayUploadFiles(object sender, DoWorkEventArgs e)
{
try
{
UploadedFiles = files;
foreach (string fn in files)
{
BackgroundWorker bw = sender as BackgroundWorker;
f = e.Argument as FtpSettings;
MakeDir(f.TargetFolder);
string UploadPath = String.Format("{0}/{1}{2}", f.Host, f.TargetFolder == "" ? "" : f.TargetFolder + "/", Path.GetFileName(fn));
if (!UploadPath.ToLower().StartsWith("ftp://"))
UploadPath = "ftp://" + UploadPath;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(UploadPath);
request.UseBinary = true;
request.UsePassive = f.Passive;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Timeout = 300000;
request.Credentials = new NetworkCredential(f.Username, f.Password);
long FileSize = new FileInfo(fn).Length;//f.SourceFile).Length;
string FileSizeDescription = GetFileSize(FileSize);
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;
byte[] Buffer = new byte[ChunkSize];
using (Stream requestStream = request.GetRequestStream())
{
using (FileStream fs = File.Open(fn, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
int BytesRead = fs.Read(Buffer, 0, ChunkSize);
while (BytesRead > 0)
{
try
{
if (bw.CancellationPending)
return;
requestStream.Write(Buffer, 0, BytesRead);
SentBytes += BytesRead;
string SummaryText = String.Format("Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
bw.ReportProgress((int)(((decimal)SentBytes / (decimal)FileSize) * 100), SummaryText);
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex.ToString());
if (NumRetries++ < MaxRetries)
{
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize);
}
}
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
System.Diagnostics.Debug.WriteLine(String.Format("Upload File Complete, status {0}", response.StatusDescription));
}
//}
}
catch (WebException ex)
{
switch (ex.Status)
{
case WebExceptionStatus.NameResolutionFailure:
ConnectionError = "Error: Please check the ftp address";
break;
case WebExceptionStatus.Timeout:
ConnectionError = "Error: Timout Request";
break;
}
}
}
我现在尝试使用希伯来语在文件名中上传一个文件。 在变量文件中,我看到带有希伯来字母的文件很好。 上传的文件没有任何异常或问题。
这就是ftp服务器上的文件在用gibrish上传之后的样子:
我该怎么办?在上传方法中进行上传之前的编码应该解决吗?如果是这样我怎么做编码?
答案 0 :(得分:0)
可能就像更改FTP服务器或configuring to support Unicode characters或切换到SFTP一样简单。
如果符合RFC 2640的客户端发送OPTS UTF-8 ON,则无论OPTS UTF-8 ON是否成功,都必须使用UTF-8。符合RFC 2640的服务器不得使UTF-8依赖于OPTS UTF-8 ON。
Ftp create a filename with utf-8 chars such as greek, german etc
如果这不是一个选项,那么我担心在这种情况下你必须自己执行文件名编码和解码。
const string fileName = "100%ץצקרתﬤﬢ.jpg";
var bytes = Encoding.Unicode.GetBytes(fileName);
var doubleBytes = bytes.ToObservable().Buffer(2);
var asciiFileName = new StringBuilder();
doubleBytes.Subscribe(
s =>
asciiFileName.Append(s[1] == 0
? (s[0] == 37 ? "%25" : Convert.ToString((char) s[0]))
: String.Format("%{0:X2}%{1:X2}", s[0], s[1]).PadLeft(2, '0')));
我完全懒惰,依靠Reactive Extensions为我缓冲数据。
asciiFileName的值将是
100%25%E5%05%E6%05%E7%05%E8%05%EA%05%24%FB%22%FB.jpg
不是最漂亮的,但它保留了原始角色。你可能会遇到左对齐和右对齐字符串的其他挑战,所以线程轻微......:)
如果你不想使用Rx,那么这个扩展就可以解决问题:
public static class Extensions
{
public static IEnumerable<byte[]> ToBytePairs(this byte[] array)
{
var enumerator = array.GetEnumerator();
while (enumerator.MoveNext())
{
var bytePair = new byte[2];
bytePair[0] = (byte)enumerator.Current;
enumerator.MoveNext();
bytePair[1] = (byte)enumerator.Current;
yield return bytePair;
}
}
}
我希望这会给你一个开始,但你必须自己编写相反的程序。 :)
<强>更新强>
我拿了一个Microsoft示例并确认它适用于FileZilla服务器(之前提到过)
#region
using System;
using System.IO;
using System.Net;
using System.Threading;
#endregion
namespace FtpUnicodeClient
{
public class FtpState
{
private readonly ManualResetEvent _wait;
public FtpState()
{
OperationException = null;
_wait = new ManualResetEvent(false);
}
public ManualResetEvent OperationComplete
{
get { return _wait; }
}
public FtpWebRequest Request { get; set; }
public string FileName { get; set; }
public Exception OperationException { get; set; }
public string StatusDescription { get; set; }
}
public class AsynchronousFtpUpLoader
{
// Command line arguments are two strings:
// 1. The url that is the name of the file being uploaded to the server.
// 2. The name of the file on the local machine.
//
public static void Main(string[] args)
{
// Create a Uri instance with the specified URI string.
// If the URI is not correctly formed, the Uri constructor
// will throw an exception.
var target = new Uri(args[0]);
string fileName = args[1];
var state = new FtpState();
var request = (FtpWebRequest) WebRequest.Create(target + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example uses anonymous logon.
// The request is anonymous by default; the credential does not have to be specified.
// The example specifies the credential only to
// control how actions are logged on the server.
request.Credentials = new NetworkCredential("demo", "demo");
// Store the request in the object that we pass into the
// asynchronous operations.
state.Request = request;
state.FileName = fileName;
// Get the event to wait on.
ManualResetEvent waitObject = state.OperationComplete;
// Asynchronously get the stream for the file contents.
request.BeginGetRequestStream(EndGetStreamCallback, state);
// Block the current thread until all operations are complete.
waitObject.WaitOne();
// The operations either completed or threw an exception.
if (state.OperationException != null)
{
throw state.OperationException;
}
Console.WriteLine("The operation completed - {0}", state.StatusDescription);
}
private static void EndGetStreamCallback(IAsyncResult ar)
{
var state = (FtpState) ar.AsyncState;
// End the asynchronous call to get the request stream.
try
{
Stream requestStream = state.Request.EndGetRequestStream(ar);
// Copy the file contents to the request stream.
const int bufferLength = 2048;
var buffer = new byte[bufferLength];
int count = 0;
int readBytes;
FileStream stream = File.OpenRead(state.FileName);
do
{
readBytes = stream.Read(buffer, 0, bufferLength);
requestStream.Write(buffer, 0, readBytes);
count += readBytes;
} while (readBytes != 0);
Console.WriteLine("Writing {0} bytes to the stream.", count);
// IMPORTANT: Close the request stream before sending the request.
requestStream.Close();
// Asynchronously get the response to the upload request.
state.Request.BeginGetResponse(EndGetResponseCallback, state);
}
// Return exceptions to the main application thread.
catch (Exception e)
{
Console.WriteLine("Could not get the request stream.");
state.OperationException = e;
state.OperationComplete.Set();
}
}
// The EndGetResponseCallback method
// completes a call to BeginGetResponse.
private static void EndGetResponseCallback(IAsyncResult ar)
{
var state = (FtpState) ar.AsyncState;
try
{
var response = (FtpWebResponse) state.Request.EndGetResponse(ar);
response.Close();
state.StatusDescription = response.StatusDescription;
// Signal the main application thread that
// the operation is complete.
state.OperationComplete.Set();
}
// Return exceptions to the main application thread.
catch (Exception e)
{
Console.WriteLine("Error getting response.");
state.OperationException = e;
state.OperationComplete.Set();
}
}
}
}
检查您的FTP日志文件。似乎FtpWebRequest客户端已经发送了所需的命令:
(000005)12/26/2014 15:17:15 PM - (not logged in) (::1)> Connected on port 21, sending welcome message...
(000005)12/26/2014 15:17:15 PM - (not logged in) (::1)> USER demo
(000005)12/26/2014 15:17:15 PM - (not logged in) (::1)> 331 Password required for demo
(000005)12/26/2014 15:17:15 PM - (not logged in) (::1)> PASS ****
(000005)12/26/2014 15:17:15 PM - demo (::1)> 230 Logged on
(000005)12/26/2014 15:17:15 PM - demo (::1)> OPTS utf8 on
(000005)12/26/2014 15:17:15 PM - demo (::1)> 202 UTF8 mode is always enabled. No need to send this command.
(000005)12/26/2014 15:17:15 PM - demo (::1)> PWD
(000005)12/26/2014 15:17:15 PM - demo (::1)> 257 "/" is current directory.
(000005)12/26/2014 15:17:15 PM - demo (::1)> TYPE I
(000005)12/26/2014 15:17:15 PM - demo (::1)> 200 Type set to I
(000005)12/26/2014 15:17:15 PM - demo (::1)> EPSV
(000005)12/26/2014 15:17:15 PM - demo (::1)> 229 Entering Extended Passive Mode (|||7800|)
(000005)12/26/2014 15:17:15 PM - demo (::1)> STOR 100ץצקרתﬤﬢ.txt
(000005)12/26/2014 15:17:15 PM - demo (::1)> 150 Opening data channel for file upload to server of "/100ץצקרתﬤﬢ.txt"
(000005)12/26/2014 15:17:15 PM - demo (::1)> 226 Successfully transferred "/100ץצקרתﬤﬢ.txt"
(000005)12/26/2014 15:17:15 PM - demo (::1)> disconnected.