C# · 12月 25, 2021

c# – 比较两个文件在互联网上是否相同

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

用于获取文件的代码是:

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));}解决方法 通常的解决方案是在某处保留云文件的哈希值,通常在文件的元数据中,并将其与本地文件的哈希值进行比较.校验和不适合此操作,因为它们具有很高的冲突机会(即具有相同校验和的不同文件).

大多数存储服务(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的Data 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(); …}