Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 仅当映像较新时,如何从HTTP下载映像?_C#_.net_Http - Fatal编程技术网

C# 仅当映像较新时,如何从HTTP下载映像?

C# 仅当映像较新时,如何从HTTP下载映像?,c#,.net,http,C#,.net,Http,我想实现以下功能: C#客户端连接到HTTP服务器并将映像下载到磁盘 下次客户端启动时,将检查服务器上的映像是否比磁盘上的映像更新,在这种情况下,客户端将覆盖磁盘上的映像 对我来说,下载映像很容易,但我不确定如何检查服务器上的映像是否更新。我如何实现它?我想我可以检查时间戳或图像大小(或两者都检查),但我不知道怎么做。如果在请求字段中修改,请尝试。 我不确定每个服务器是否都完全支持它。因此,如果它不被支持并且仍将得到该文件(如果支持它,则不是304),则可以计算校验和,如果它们不同,请考虑修改文

我想实现以下功能:

  • C#客户端连接到HTTP服务器并将映像下载到磁盘

  • 下次客户端启动时,将检查服务器上的映像是否比磁盘上的映像更新,在这种情况下,客户端将覆盖磁盘上的映像


  • 对我来说,下载映像很容易,但我不确定如何检查服务器上的映像是否更新。我如何实现它?我想我可以检查时间戳或图像大小(或两者都检查),但我不知道怎么做。

    如果在请求字段中修改,请尝试
    。
    我不确定每个服务器是否都完全支持它。因此,如果它不被支持并且仍将得到该文件(如果支持它,则不是304),则可以计算校验和,如果它们不同,请考虑修改文件。或者只是覆盖-您将始终拥有最新版本。

    您需要阅读和相关的RFC(搜索1616 at)。特别值得一提的是,§13,HTTP缓存,第47-62页。然后阅读相关的请求/响应标题以及您可能得到的相关状态代码

    您可以通过
    HttpWebRequest
    HttpWebResponse
    类访问所有标题和状态值

    但是需要注意的是,您可以向服务器请求您想要的任何东西:最终是服务器决定是否向您发送该URI的新表示。您可能希望使用HTTP谓词而不是其谓词来询问服务器有关资源的信息

    HEAD方法与GET相同,只是服务器不能返回 响应中的消息体。HTTP头中包含的元信息 对HEAD请求的响应应与发送的信息相同 对GET请求的响应。此方法可用于获取元信息 关于请求隐含的实体,而不转移实体体本身。 此方法通常用于测试超文本链接的有效性、可访问性、, 以及最近的修改


    HttpWebRequest可以只使用IE缓存,因此,如果所有图像都将在该缓存中,并且重新写入文件(但不必下载)的成本是可以接受的,那么您可以利用它

    如果您需要自己处理,那么:

    鉴于:

    string uri; //URI of the image.
    DateTime? lastMod; // lastModification date of image previously recorded. Null if not known yet.
    string eTag; //eTag of image previously recorded. Null if not known yet.
    
    您必须在本文末尾存储这些图像,并在开始时再次检索它们(如果不是新图像)。这取决于你,考虑到这一点,剩下的工作:

    var req = (HttpWebRequest)WebRequest.Create(uri);
    if(lastMod.HasValue)
      req.IfModifiedSince = lastMod.Value;//note: must be UTC, use lastMod.Value.ToUniversalTime() if you store it somewhere that converts to localtime, like SQLServer does.
    if(eTag != null)
      req.AddHeader("If-None-Match", eTag);
    try
    {
      using(var rsp = (HttpWebResponse)req.GetResponse())
      {
        lastMod = rsp.LastModified;
        if(lastMod.Year == 1)//wasn't sent. We're just going to have to download the whole thing next time to be sure.
          lastMod = null;
        eTag = rsp.GetResponseHeader("ETag");//will be null if absent.
        using(var stm = rsp.GetResponseStream())
        {
          //your code to save the stream here.
        }
      }
    }
    catch(WebException we)
    {
      var hrsp = we.Response as HttpWebResponse;
      if(hrsp != null && hrsp.StatusCode == HttpStatusCode.NotModified)
      {
        //unfortunately, 304 when dealt with directly (rather than letting
        //the IE cache be used automatically), is treated as an error. Which is a bit of
        //a nuisance, but manageable. Note that if we weren't doing this manually,
        //304s would be disguised to look like 200s to our code.
    
        //update these, because possibly only one of them was the same.
        lastMod = hrsp.LastModified;
        if(lastMod.Year == 1)//wasn't sent.
          lastMod = null;
        eTag = hrsp.GetResponseHeader("ETag");//will be null if absent.
      }
      else //some other exception happened!
        throw; //or other handling of your choosing
    }
    
    正确实施时,电子标签比上次修改的更可靠(注意更改的秒级分辨率,并反映由于不同的Accept-*标头而产生的不同响应)。不过,有些实现存在缺陷(在web场上没有特殊调整的IIS6,Apache带有mod gzip),因此删除与电子标签相关的代码并按日期执行是值得的


    编辑:如果您想进一步实现HTTP缓存,还可以存储expires和max age(如果两者都存在并且与前者不一致,则使用后者),如果它们早于这些值,则完全跳过下载。我已经这样做了,而且效果很好(我有一个内存缓存,其中的对象是由从各种URI返回的XML创建的,如果XML是新的或没有更改,我会重新使用该对象),但是它可能与您的需要无关(如果您希望比服务器建议的更新鲜,或者如果您总是在该窗口之外).

    您可能对此感兴趣:您是否可以控制web服务器?如果不支持,它是否支持缓存、ETag等。。。当服务这些图像时?不确定这将如何通过HTTP工作,但您可以尝试。我不确定的原因是,我无法判断财产的价值是实际的创建日期还是您上次访问它的日期(我对这个问题有点无知)。“这值得一看,”达林:不,我没有。服务器远程且未知。我需要做的是类似于代理或navigator缓存的事情。我想缓存一个资源,当它是新的时刷新它。不支持它的服务器很少。您有时会发现并非每个资源都支持它(例如,ASP.NET或PHP页面默认情况下不支持,因为它需要逻辑来知道发送的日期,尽管它们当然可以支持),但至少所有服务器都支持“抱歉,我不知道,事情就是这样”而不是扼杀它。我给的代码使用了这个,还有电子标签。发送HEAD有什么用?要么它将发送一个304,在这种情况下它与GET相同,要么它将发送一个200,在这种情况下,唯一能确保的方法是在它之后发送一个GET;可能得到,也可能得不到。HEAD将允许您在不检索新表示的情况下使缓存项无效。根据需求,延迟向缓存中添加新表示可能是首选行为。因此,在我的答案中有条件的“可能”。但是在HEAD返回200的情况下,我们可能知道我们肯定想要得到(不同的内容长度),但不是我们肯定不会得到(如果它们是相同的内容长度,它们可能仍然是不同的图像),所以我们无论如何都必须得到。唯一的可能性是,如果有人发送MD5头文件,而没有发送最后一个mod或e-tags,这在技术上是可能的,但足够反常,这样的人会受到一记耳光,在现实生活中也不太可能(MD5头文件很少见,最后一个mod和e-tags是几乎所有服务器上的“静态文件”的默认行为,有时甚至更高)。