【问题标题】:.NET error when calling System.Net.WebClient.UploadFileAsync调用 System.Net.WebClient.UploadFileAsync 时出现 .NET 错误
【发布时间】:2011-06-14 19:16:06
【问题描述】:

我正在使用 System.Net.WebClient 类,我正在尝试使用 UploadFileAsync 方法上传文件。我正在使用 Visual Studio 2010,我的所有项目都设置为使用 .NET 4.0 标准运行时,而不是客户端库。

下面是我正在使用的一小部分代码。大约 90% 的时间我会收到以下错误:

无法将“System.ComponentModel.AsyncOperation”类型的对象转换为“UploadBitsState”类型。

Stack Trace:
 at System.Net.WebClient.UploadFileAsyncWriteCallback(Byte[] returnBytes, Exception exception, Object state)
 at System.Net.WebClient.UploadFileAsync(Uri address, String method, String fileName,   Object userToken)
 at FileUpload._StartUpload()

我尝试上传到的 FTP 服务器在我的组织内部,但一台运行 IPSwitches WS-FTP,另一台运行 IIS 6.0 FTP 站点,我在两台服务器上都遇到了同样的问题。

我已经到处寻找有类似问题的其他人,但无济于事。

发生异常的实际行是_Client.UploadFileAsync方法调用。

private void _StartUpload()
{
    try
    {
        _Client = new WebClient
        {
            Credentials = _Credentials
        };
        _Client.UploadProgressChanged += ProgressChanged;
        _Client.UploadFileCompleted += UploadCompleted;
        _Client.UploadFileAsync(FileBeingUploaded, "STOR", _LocalFile, null);
    }
    catch (Exception exception)
    {
        // Methods calls removed for brevity
    }
}

private void UploadCompleted(Object sender, UploadFileCompletedEventArgs e)
{
    // Methods calls removed for brevity
}

private void ProgressChanged(object sender, UploadProgressChangedEventArgs e)
{
    // Methods calls removed for brevity
}

【问题讨论】:

  • 同步执行是否有效?您是否尝试过使用诸如tcpdumpWireShark 之类的数据包嗅探器来查看流量?
  • 我没有尝试过同步调用。至于嗅探器,我没有尝试观察这些具体错误,但鉴于异常在 .Net 框架内并且是演员表问题,我不确定 TCP 流量分析会显示什么。
  • 你上传的文件_LocalFile是静态文件吗?换句话说,是否有任何文件的内容在上传时被修改/更新的可能性?我问是因为我可以在那种特定情况下复制你的错误。
  • 遗憾的是没有。私有字符串_LocalFile;私有 NetworkCredential _Credentials;不过,这是一个有趣的观察,我会看看是否有任何东西可以与文件名混淆。

标签: .net exception webclient


【解决方案1】:

这很有趣。查看参考源(WebClient.cs),UploadFileAsyncWriteCallback 的第一行将state 参数强制转换为UploadBitsState

在方法UploadFileAsync中,有一段异常处理代码如下:

catch (Exception e)
{
    if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
    { 
        throw; 
    }
    if(fs != null){ 
        fs.Close();
    }
    if (!(e is WebException || e is SecurityException)) {
        e = new WebException(SR.GetString(SR.net_webclient), e); 
    }
    UploadFileAsyncWriteCallback(null, e, asyncOp); 
}

asyncOp 的类型为 AsyncOperation

看起来对UploadFileAsyncWriteCallback 的调用是一个错误,因为它将错误类型的对象传递给回调。回调执行 C 风格转换(即UploadBitsState uploadState = (UploadBitsState)state;)。

但这只有在上传过程中触发异常时才会发生。

您的ProgressChangedUploadCompleted 事件处理程序中是否有可能引发异常?您传递给UploadFileAsync 的参数或其中一个参数无效。

更多信息

看起来UploadFileAsync 中确实存在错误。例如,以下抛出InvalidCastException,根据文档应该抛出WebException

var targetUri = new Uri("ftp://example.com/file.txt");
var srcFile = string.Empty;  // documentation says this will throw WebException
var client = new WebClient();
client.UploadFileAsync(targetUri, "STOR", srcFile, null);

我已经在https://connect.microsoft.com/VisualStudio/feedback/details/675575/webclient-uploadfileasync-throws-invalidcastexception报告了这个错误

但是,从表面上看,我会说引发异常的原因在于您的代码。不幸的是,不可能说在哪里,因为UploadFileAsync 正在丢失异常信息。也许,正如其他人指出的那样,尝试同步上传会更清楚地说明这个问题。

【讨论】:

  • 两个事件处理函数都以 try { 开始并以 } catch (Exception exception) { // 处理异常 } 结束,所以我认为他们没有做任何不恰当的事情。您的回答和上面的评论都指向导致问题的输入参数。我将不得不看看是否有任何意外正在改变这些值。
  • @DaleCouch:抱歉,我指的是您正在上传的磁盘驱动器上的实际数据文件。例如,如果它是某个其他应用程序的日志文件。如果在您上传时其他应用程序仍在运行,则其他应用程序可能会将更多日志记录数据附加到日志中。这可能会使 Webclient 感到困惑,因为它开始认为它正在上传 200 字节,但发现文件现在有 250 字节长。不过都是我的猜测。
  • @j.w.r.:现在这似乎更有意义了。这是可能的。所有这些文件都是实时生成的,我只是在尝试传输它们之前关闭了它们。因此,操作系统很有可能正在迎头赶上。我会尝试改变我的做法,看看是否有帮助。感谢您提供可能的方向。
  • @Dale:你能确定你的任何一个事件处理程序是否被调用过吗?这将帮助您缩小可能性。
  • @Jim:看起来不是这样。失败几乎是立竿见影的。
猜你喜欢
  • 2021-06-29
  • 2013-03-06
  • 2015-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 2018-04-20
相关资源
最近更新 更多