【问题标题】:Compare if two file are the same over the internet比较两个文件在互联网上是否相同
【发布时间】:2013-08-10 02:07:55
【问题描述】:

这是我的场景 - 我有一个 Windows 商店应用程序。我有一个本地文件,以及一个指向 Internet 上文件的链接。有没有办法检查这两个文件是否相同,从链接下载文件?

用来获取文件的代码是这样的:

private static async void SetImage(PlaylistItem song, string source, string imageName)
{

    HttpClient client = new HttpClient();

    HttpResponseMessage message = await client.GetAsync(source);

    StorageFolder myfolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    StorageFile sampleFile = await myfolder.CreateFileAsync(imageName, CreationCollisionOption.ReplaceExisting);
    byte[] byteArrayFile = await message.Content.ReadAsByteArrayAsync();

    await FileIO.WriteBytesAsync(sampleFile, byteArrayFile);

    song.Image = new BitmapImage(new Uri(sampleFile.Path));

}

【问题讨论】:

  • 您使用的是什么存储服务?大多数服务将哈希用于并发目的,但您检索它们的方式可能会有所不同
  • 有问题的文件是 youtube 视频缩略图
  • Best way to tell if two files are the same? 的副本。此外,您的问题是一个单行程序,并没有表明您理解问题(您是否研究过任何比较文件的方法以及为什么它们不够用?)或者您已经尝试过任何事情。
  • @CodeCaster 如果措辞不完美,这个问题是有效的。您指向的帖子不适用于网络托管文件。这更像是一个 HTTP 问题
  • @PanagiotisKanavos 虽然这个问题本身是有效的,但它目前的格式显示没有对 OP 本人进行任何研究,这是 SO 所必需的。如果 OP 真的解释了他的实际问题(为什么比较 YouTube 缩略图)并解释了已经尝试过的内容,那将是一个更好的问题。

标签: c# file http-headers youtube-api windows-store-apps


【解决方案1】:

通常的解决方案是将云文件的哈希保存在某处,通常在文件的元数据中,并将其与本地文件的哈希进行比较。校验和不适合此操作,因为它们发生冲突的可能性非常高(即不同的文件具有相同的校验和)。

大多数存储服务(Azure Blob 存储、Amazon S3、CloudFiles)实际上使用文件的 MD5 或 SHA 哈希作为其 ETag,该值用于检测文件更改以用于缓存和并发目的。通常,对文件的 HEAD 操作将返回其标题和 ETag 值。

如果您可以选择自己的算法,请选择 SHA256 或更高版本,因为这些算法经过高度优化,并且它们的大块大小意味着计算大文件的哈希值要快得多。 SHA256 实际上比旧的 MD5 算法快得多。

您使用的是什么存储服务?

编辑

如果您只想检查文件以避免再次下载,您可以直接使用 ETag。 ETag 正是为此目的而创建的。当您第一次下载它时,您只需要将它与您的文件一起存储。这就是代理和缓存知道向您发送图片的缓存版本而不是访问目标服务器的方式。

事实上,您可能只需对带有 ETag/If-None-Match 标头的文件执行 GET 操作。如果目标文件未更改,则中间代理和最终 Web 服务器将返回 304 状态代码。这将使您下载列表中所有图片所需的请求数量减半。

另一种方法是存储文件的 Last-Modified 标头值并在 GET 中使用 If-Modified-Since 标头

编辑 2

您提到 ETag 标头为空,尽管您的代码没有显示您如何检索它。

HttpResponseMessage 有多个 Headers 属性,on the message itself 和它的 Content。您需要使用适当的属性来检索 ETag 值。

您还可以使用 Fiddler 检查以确保服务器确实返回了 ETag。

编辑 3

终于找到了从 Youtube 获取 ETag 的方法!答案来自“How to get thumbnail of YouTube video link using YouTube API?

在来自ytimg.com 的 YouTube 缩略图上执行 HEAD 或 GET 不会返回 ETag 或 Last-Modified 标头。

另一方面,使用 YouTube 的数据 API 并在 gdata.youtube.com 上执行 GET,会返回有关视频的大量信息。包含一个 ETag 值,尽管我怀疑它会随着视频的变化而变化。但是,如果您只想在视频更改时下载图像,或者您不想再次下载图像,这可能没问题。

我使用的代码是:

var url = "http://gdata.youtube.com/feeds/api/videos/npvJ9FTgZbM?v=2&prettyprint=true&alt=json";

using(var  client = new HttpClient())
{
    var response = await client.GetAsync(url);
    var etag1 = response.Headers.ETag;
    var content = await response.Content.ReadAsStringAsync();
    ...
}

【讨论】:

  • none,这个想法是用户正在浏览互联网上的图像列表(该列表不是我的,它们所在的地方也不是我的)并且我想限制带宽使用,即如果用户已经拥有此图像,请不要下载它,只需从本地存储中加载它即可。有问题的图片是 youtube 视频缩略图。
  • 这可能是一个更简单的情况。仅当文件已更改时,您才能使用带有 If-XXX 标头的 HTTP GET 来获取文件
  • 这可能是服务器或您的代码的问题。请张贴代码。最后修改的呢?你打的是什么网址?它是公开的吗?
【解决方案2】:

您可以像 git 一样计算文件内容的哈希值。使用 MD5 或类似的。那么你只需要检查文件是否具有相同的哈希值。

【讨论】:

  • 除非在线文件已经有可用的关联校验和,否则操作员仍需要下载文件才能运行检查。
  • 大多数存储服务已经为此使用哈希(不是校验和)。通常它们存储为文件的 ETag 值
  • 顺便说一句,长度和哈希只是标题,通常由同一个调用返回。
【解决方案3】:

如果您想在不下载的情况下进行比较,并且您就是将文件放到互联网上的人。那么理想情况下,您应该放置一个校验和上传的文件。然后在上传新文件之前,您只需检查本地文件和服务器上文件的校验和。如果不相等则继续上传,否则取消。

【讨论】:

    【解决方案4】:

    直接?不会。如果在线的文件也提供了一个哈希,但是你可以成功检查文件的相等性的概率很高。

    【讨论】:

      【解决方案5】:

      现在,随着您的更新,您的代码所做的工作很清楚:它从给定的 URL 下载图像并将其存储在给定文件名下的应用程序数据文件夹中。您只想下载任何图像一次。

      我仍然不清楚你如何调用这段代码,但对我来说,解决方案看起来你只需要一个“URL 到文件名”的翻译。所以,在伪:

      BitmapImage GetImage(string sourceURL)
      {
          string filename = GetFilenameForURL(sourceURL);
      
          BitmapImage image;
      
          if (!FileExists(filename))
          {
              image = DownloadAndSaveImage(sourceURL, filename);
          }
          else        
          {       
              image = ReadImageFile(filename);
          }
      
          return image;
      }
      

      这不考虑服务器上已更新的图像。如果您想这样做,您需要在DownloadAndSaveImage() 调用中保存元数据,例如提到的ETaglast-modified 日期。

      然后,为了节省带宽,您可以在调用 ReadImageFile() 之前使用 if-none-matchif-modified-since 标头发出 HEAD 或有条件的 GET 请求,以检查是否有更新的版本可用。

      【讨论】:

        猜你喜欢
        • 2022-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多