C # Каков наилучший способ вычислить хэш канала XML - PullRequest
3 голосов
/ 24 октября 2011

Я хочу определить, изменился ли фид. Единственный способ, которым я могу придумать, - это хэшировать содержимое XML-документа и сравнивать его с последним хешем фида.

Я использую XmlReader, потому что SyndicationFeed использует его, поэтому в идеале я не хочу загружать фид синдикации, если фид не был обновлен.

XmlReader reader = XmlReader.Create("http://www.extremetech.com/feed");
SyndicationFeed feed = SyndicationFeed.Load(reader);

Ответы [ 3 ]

3 голосов
/ 25 октября 2011

Если вы действительно хотите использовать хеш, вы можете сделать следующее:

var client = new WebClient();

var content = client.DownloadData("http://www.extremetech.com/feed");

var hash = MD5.Create().ComputeHash(content);
var hashString = Convert.ToBase64String(hash);

// you can then compare hashes and if changed load it this way
XmlReader reader = XmlReader.Create(new MemoryStream(content));

Конечно, если вы пойдете таким образом, вы обнаружите любые изменения в контенте, даже самые незначительные.

IMHO, лучший способ - это загрузить канал и хэшировать только содержимое статей. Вы можете хэшировать любую строку, например, такую:

var toHash = "string to hash";

var hash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(toHash);
var hashString = Convert.ToBase64String(hash);

Надеюсь, это поможет.

3 голосов
/ 24 октября 2011

Почему бы просто не проверить LastUpdatedTime канала?Это встроенный способ сказать вам, что-то новое или нет.Вместо хеширования и хранения хеш-функции вы просто следите за LastUpdatedTime и периодически сравниваете его с последним LastUpdatedTime:

using System;
using System.ServiceModel.Syndication;
using System.Xml;

public class MyClass
{
    private static DateTime _lastFeedTime = new DateTime(2011, 10, 10);

    public static void Main()
    {
        XmlReader reader = XmlReader.Create("http://www.extremetech.com/feed");
        SyndicationFeed feed = SyndicationFeed.Load(reader);

        if (feed.LastUpdatedTime.LocalDateTime > _lastFeedTime)
        {
            _lastFeedTime = feed.LastUpdatedTime.LocalDateTime;

            // load feed...
        }
    }
}
2 голосов
/ 25 октября 2011

В этом случае хеш-подход не будет работать из-за XML-комментария, добавляемого некоторым кэшированием на стороне сервера, которое постоянно очень часто, даже когда реальный фид никогда не меняется.

Единственное, что вы можете сделать для этого фида, - это использовать условные запросы HTTP, чтобы запросить у сервера данные, только если они действительно были изменены с момента последнего запроса.

Например:

У вас будет глобальная переменная / переменная-член, которая будет содержать дату последнего изменения даты и времени из вашего канала

    var lastModified = DateTime.MinValue;

Тогда каждый раз, когда вы делаете запрос, подобный следующему

    var request = (HttpWebRequest)WebRequest.Create( "http://www.extremetech.com/feed" );
    request.IfModifiedSince = lastModified; 
    try {

      using ( var response = (HttpWebResponse)request.GetResponse() ) {

        lastModified  = response.LastModified;

        using ( var stream = response.GetResponseStream() ) {

          //*** parsing the stream
          var reader = XmlReader.Create( stream );
          SyndicationFeed feed = SyndicationFeed.Load( reader );
          }
        }
      }
    catch ( WebException e ) {
      var response = (HttpWebResponse)e.Response;
      if ( response.StatusCode != HttpStatusCode.NotModified )
        throw; // rethrow an unexpected web exception
      }
...