2013-04-29 1 views
2

서버 쪽 헤더를 제어하거나 추가 할 수 없다면 전체 파일을 다운로드하지 않고 로컬 체크섬과 원격 파일을 비교하고 비교할 수 있습니까? Ruby와 Net :: HTTP를 사용하는 체크섬전체 파일을 다운로드하지 않고 Ruby에서 Net :: HTTP를 사용하여 체크섬과 로컬 파일 비교하기

Net :: HTTP를 사용하여 작성한 클래스를 사용하여 디스크로 파일을 채우고 있습니다. 내 로컬 파일의 SHA256 합계와 비교하여 원격 파일을 비교하여 대역폭 절약 성을 높이고 싶습니다. 로컬 복사본이 원격 버전과 일치하지 않을 때만 원격 파일을 다운로드하려고합니다. 여기

내 가정은 다음과 같습니다

  • 파일 이름이 동일 할 수 있지만, 내용이 다를 수 있습니다.

  • HTTP 헤더의 'Last-modified'날짜는 변경 사항을 나타내는 좋은 지표가 아닙니다. cp /dir_a/file1.tar /dir_b/file2.tar은 동일한 체크섬을 갖지만 '마지막으로 수정 된'시간은 다릅니다.

  • HTTP 헤더 Etags는 좋지 않습니다. http://example.org/file1.tarhttp://example.iana.org//file1.tar은 동일한 파일에 대해 다른 Etags를 가질 수 있습니다.

  • HTTP 헤더 Etags는 완전히 표준이 아닙니다. EC2는 Etags를 생성하는 데 md5sums를 사용하지만 다른 호스트는 그렇지 않을 수도 있습니다. 이렇게하면이 태그 값의 로컬 생성이 어려워집니다.

  • 호스트 이름 -Etag 구현의 해시/사전을 유지 관리하는 것은 다루기 어렵고 나쁜 접근입니다.

나 서버 측 소프트웨어는 이러한 목표를 달성하기 위해 머리글 또는 별도의 look-에서 (예를 들어, 체크섬 필드 파일/태그/체크 6 비교를 수행하기위한 기능을 제공해야한다는 것을 상대적으로 확신하지만 up 파일),이 추격을 포기하기 전에 내 가정에 대한 확인을 원합니다. 산만 함을 피하기 위해 기존 코드를 생략했습니다. 구현 방법에 대해 살펴 보았습니다.

+0

흥미로운; 나는 믿을 수 없다. (리눅스 배포판이 체크섬 파일과 함께 분배되는 것은 합리적인 파일이라고 생각한다.) 그러나 "마법"트릭이 있다면 궁금하다. – mdesantis

+0

ETags 생성을위한 표준은 없다. 팜의 각 서버에서 서로 다를 수 있습니다 (예 : 파일의 파일 시스템 inode를 기반으로하는 경우). 마지막 수정 시간은 서버마다 다를 수 있습니다. 웹 서버가 특정 파일의 해시를 제공하도록 요청하는 메커니즘이 없습니다. 이는 웹 서버에 대한 서비스 거부를 실행하는 훌륭한 방법입니다. 개체 저장소 시스템 (예 : Amazon S3)은 개체가 저장 될 때 해시를 계산하고 메타 데이터에 유지 관리하지만 기본적으로 웹 서버에서는 찾지 않습니다. – NevDull

+0

@NevDull 결과 체크섬이 캐시되지 않은 경우 서버에로드를 생성하는 데 사용할 수 있습니다 (예 : i7의 shasum5.12 시간 : shasum5.12 ubuntu-12.04.1-server-amd64 .iso 2.16s 사용자 0.36s 시스템 87 % CPU 2.870 총'), 특히 대용량 파일이나 큰 파일 목록. 나는 내가 그것을 열었을 때 (내가 묻기 전에 약간의 연구를했듯이) 내가 내 자신의 질문에 대답 할 것이라고 확신했다. 누군가가 @ProGNOMmers가 언급 한 것처럼 영리한 해킹이나 '마법'을 가지고 있지 않다면, 나는 내 자신의 연구를 게시하고 동의 할 것이다. –

답변

1

유감스럽게도 내 경우에는 표준 HTTP 헤더 또는 Net :: HTTP 요청을 사용하여 미리 계산 된 체크섬을 가져 오는 방법이 없습니다.

솔루션 : 서버의 제어에 있다면

, 당신은 Nginx 또는 Apache와 같은 임의의 헤더를 추가 할 수 있습니다.

{ "md5-files": [ 
    {"file1" : "60b725f10c9c85c70d97880dfe8191b3"}, 
    {"file2" : "18ac6fe7ca693bb1767982e2eb3bbd0d") 
]} 

하나의 거울려고 경우

대안 적으로, 하나는 JSON의 다음 (대충) 예로서, 파일/체크 용 키/값 쌍으로 구조화 사전 파일을 생성하고 노출 될 동일한 파일을 여러 서버에 구축하려는 경우 구조화 된 배열 을 로컬로에 작성하고 파일이 변경된 사실을 알리기 위해 하나의 서버 만 사용해야합니다. (예 : master-download-server-1은 http://example.org/file1, 로컬 버전과 비교 한 다음 파일을 업데이트합니다.이 파일은 slave-download-s로 구문 분석 될 수 있습니다. erver1, slave-download-server2를 사용하여 example.org (또는 master-download-server-1 자체)에 요청을 보내야하는지 확인하십시오.

마지막으로 Amazon S3에서 자주 다운로드 할 때 클라이언트 전용 서비스로 사용할 수있는 옵션 만 사용했습니다. etag을 헤더에 반환했습니다. 불행하게도,이 설명서는 없는 큰,하지만 여기 내 접근 방식의 거친 조각입니다 :

... 
#I actually call my own encryption-helper, filename-parsing methods, 
#but meta-code for the sake of example: 
def example_file_getter(uri, docroot, file) 
    checksum = Digest::MD5.hexdigest(File.read(file)) 

    uri = URI.parse(uri) 
    http = Net::HTTP.new(uri.host, uri.port) 
    request = Net::HTTP::Get.new(uri.request_uri) 
    response = http.request(request) 

    if response['etag'] != nil 
     etag = response['etag'].gsub!(/\"/,'') 
    end 

    if etag == checksum 
     file_existed = true 
    end 

    if ! File::exists?(destination) && ! file_existed 
    ...actually fetch the file  
... 

[다시, 메타 코드; 이것은 원래의 질문과 관련된 중요한 부분을 요약 한 것입니다.]

다시 말하면, etag 문서는 훌륭하지 않으며 아마존은 어떤 시점에서 경고없이 이것을 바꿀 것으로 예상합니다. 파일이 5기가바이트 미만 및/비 'multipart 스트리밍 된

  1. 경우 '나는 다양한 forum responses 다음과 같이 (!) 아마존 직원에서, 태그의 일반적인 알고리즘은에서 함께 재현 한 바로는 서버에 업로드되면 etag는 업로드 된 파일의 md5 일 가능성이 높습니다.
  2. 파일이 5GB 이상이거나 'multipart'를 통해 업로드 된 경우 etag는 업로드 된 파일의 마지막 덩어리로 md5- #으로 표시됩니다. 여기서 #는 파일의 일부입니다 (예 : 업로드 된 파일 3 개를 볼 수 있음). 헤더에 18ac6fe7ca693bb1767982e2eb3bbd0d-3처럼).

완벽하지는 않지만 원격 호스트가 예측 가능한 패턴을 따르는 경우 헤더를 검사하여 최상의 결과를 얻으십시오.