【问题标题】:How to abort an HTTP post without reading its full contents (.NET REST service)如何在不阅读其全部内容的情况下中止 HTTP 帖子(.NET REST 服务)
【发布时间】:2012-04-23 13:53:56
【问题描述】:

我创建了一个接受二进制上传的自托管 .NET 服务。

[ServiceContract]
public interface IBinaryService
{

    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "up/file/{fileName}/{hash}")]

    void FileUpload(string fileName, string hash, Stream fileStream);

当它接收到一个文件时,它首先检查该文件是否已经在系统上,否则它会从客户端流式传输文件并保存它:

    public void FileUpload(string fileName, string hash, Stream fileStream)
    {
        string filebasedir = basedir + @"file\"; //" 
        if (File.Exists(filebasedir + hash))
        {

            WebOperationContext.Current.OutgoingResponse.StatusCode = 
                                   System.Net.HttpStatusCode.Conflict;
            return;
        }

        using(var fileToupload = new FileStream(
                string.Concat(filebasedir, hash),
                FileMode.Create))
                {
                fileStream.CopyTo(fileToupload);
                }

如果我单步执行代码,我可以看到文件内容在服务器读取参数并确定是否存在冲突之后才会流式传输。我只需要以某种方式强制服务器不读取全部内容(可能是很多兆字节)。不幸的是,使用“return”提前退出该方法并不会这样做。

这可能吗?

【问题讨论】:

  • 您是否尝试过在返回fileStream.Close();之前关闭流?
  • 谢谢。刚试了一下。不工作。
  • 这个流,我的意思是 fileStream 参数不应该手动关闭,WCF REST 基础设施会关闭它。

标签: .net wcf rest post httpwebrequest


【解决方案1】:

如果我正确理解您所面临的问题..

客户端调用方法

void FileUpload(string fileName, string hash, Stream fileStream);

一旦调用该函数,它就会开始将文件上传到服务器。 如果服务器上已经存在文件,您希望避免或中断文件上传。

你为什么不把你的方法一分为二,一种方法会检查服务器上是否已经存在文件(它只有两个参数 filename 和 hash,不要传递 filestream ),并返回 true 或 false ,如果不存在则调用第二种方法,带filestream参数。

这样应该可以解决你的问题。

【讨论】:

  • 这种方法创建了一个竞争条件,两个(或多个)客户端可以在全部上传之前同时检查文件是否不存在。同意它让事情变得不那么糟糕,而且很容易实现。
  • 是的,我想到了将它分成两个操作。希望我只需要更改一行代码就可以让 WCF 合作,但我想这不是基于答案分歧的可能性。干杯
  • @simonc 谢谢,我没有考虑竞态条件,你对处理竞态条件、一些线程同步、锁或临界区有什么建议?
【解决方案2】:

框架中的内置功能(服务器端文件上传控件)没有提供更精细的粒度来处理在上传过程中以块形式接收的数据。它只是缓冲内存中的所有数据,直到到达文件末尾或遇到错误情况。

所以你唯一的选择是:

1) 自己编写一个二进制文件上传处理程序 (httpHandler)。并非不可能,但并不像乍一看那样微不足道。这将涉及确定请求编码方法并针对可能的变化使用适当的技术来正确解码流中的编码二进制数据。

2) 一个更简单的解决方案是只使用现有的商业控件之一,它为您实现此功能并公开可用于驱动您自己的代码的事件。例如,以ABCUpload.NET 为例。另一个是PowUpload

【讨论】:

    【解决方案3】:

    可能,只返回带有错误代码的响应,不要流式传输文件

    【讨论】:

    • 怎么样?这就是我想要完成的。看我的代码。即使我在设置错误代码“冲突”后立即返回,WCF 服务也会流式传输文件。
    • 尝试抛出异常而不是返回,比如 throw new WebFaultException(System.Net.HttpStatusCode.Conflict);
    • 不走运。这具有相同的结果:(
    • 为什么你认为 WCF 流文件即使返回或抛出异常?当然,在 Stream 参数中,第一个数据块被传输到服务,但是在错误或立即返回文件的其余部分之后,其他块不会被传输到服务器。第一个块的大小取决于 maxBufferSize 配置
    • WebHttpBinding b = new WebHttpBinding(); b.MaxBufferSize = 256*1024; b.MaxReceivedMessageSize = 2147483647; b.TransferMode = TransferMode.Streamed;
    【解决方案4】:

    你可以使用OperationContext.Current.RequestContext.Abort()方法。

    【讨论】:

    • 好吧,它让服务器不接收来自客户端的完整内容。
    • 如果我理解,OP 需要在他的FileUpload 方法中中止来自客户端在服务器端,来自服务器代码 的http 请求。如果方法只是不读取流,客户端将发送此流,因为底层 TCP 连接保持打开一段时间。如果服务器中止客户端的请求,TCP 连接将被关闭,客户端将出现异常并且不会发送整个流。顺便说一句,对不起我的英语,如果有任何错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    相关资源
    最近更新 更多