我有一个非常基本的代码,可以从 FTP 服务器下载文本文件列表:
foreach (var fileUri in files)
{
try
{
var ftpRequest = (FtpWebRequest)FtpWebRequest.Create(fileUri);
ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
ftpRequest.Credentials = new NetworkCredential("***", "***");
ftpRequest.UseBinary = false;
ftpRequest.Timeout = 10_000;
ftpRequest.ReadWriteTimeout = 10_000;
using (WebResponse response = await ftpRequest.GetResponseAsync().ConfigureAwait(false))
using (var stream = response.GetResponseStream())
{
// Copy the file to an Azure storage
await CopyAsync(stream, container, GetFilename(fileUri), false).ConfigureAwait(false);
}
}
catch (Exception e)
{
Logger.Error(Unknow, $"Error downloading {fileUri.AbsoluteUri}:\n{e}");
}
}
当从 Visual Studio 运行时,此代码可以完美运行。
但是,当在 Azure 中作为 Web 作业运行时,它只会下载几个文件,然后就永远挂起。
我没有遇到超时或异常。
我添加了一些调试日志,发现它卡在了GetResponseAsync()
。
我试过没有ConfigureAwait(false)
但得到了相同的行为。
我也用过这个答案 https://stackoverflow.com/questions/9664650/output-log-using-ftpwebrequest/9666598#9666598检查网络痕迹,但我在日志中找到的所有 FTP 命令都正常。对于成功下载的每个文件,我看到以下几行,但没有看到阻止文件的任何“不完整”FTP 命令:
System.Net Information: 0 : [22712] FtpWebRequest#2543959::.ctor(ftp://<ftpserver>/<filename>)
System.Net Information: 0 : [21728] FtpWebRequest#2543959::BeginGetResponse(Method=RETR.)
System.Net Information: 0 : [21728] Associating FtpWebRequest#2543959 with FtpControlStream#64735656
System.Net Information: 0 : [21728] FtpControlStream#64735656 - Sending command [PASV]
System.Net Information: 0 : [9444] FtpControlStream#64735656 - Received response [227 Entering Passive Mode (104,45,19,12,117,54).]
System.Net Information: 0 : [9444] FtpControlStream#64735656 - Sending command [RETR <filename>]
System.Net Information: 0 : [17608] FtpControlStream#64735656 - Received response [150 Opening ASCII mode data connection for <filename> (19262 bytes)]
System.Net Information: 0 : [21804] FtpControlStream#64735656 - Received response [226 Transfer complete]
System.Net Information: 0 : [21804] FtpWebRequest#2543959::(Releasing FTP connection#64735656.)
任何帮助/领导将不胜感激!
EDIT 1
我尝试使用WebClient
代替FtpWebRequest
并得到了同样的结果。它在我的机器上完美运行,但是当在 Azure 作为 Web 作业运行时,它会下载几个文件,然后挂在webClient.DownloadFileTaskAsync(...)
线。另外,为了确保上传到 Azure 存储不会干扰该过程,我现在只需在本地下载文件即可。还有阿吉:没有例外,没有超时。它永远挂着。
EDIT 2
我尝试删除将文件上传到 Azure 存储的行,以防万一,但无济于事。然后,根据第一个评论者的建议,我添加了一个“超时包装器”,它本质上将我的代码作为任务运行,Task.Delay(10_000)
,然后等待第一个任务完成。如果下载任务先完成,那么一切都很好,但是如果Task.Delay(10_000)
首先完成,我只是中止下载请求并重试。这样做时,我观察到以下情况:首先,文件在第一次尝试时全部下载。然后,某些文件需要 2 次尝试,并且在某个时刻,尽管尝试 10 次,所有文件都会失败。所以基本上,一切开始都很好,但很快就会退化。