Получение размера файла перед загрузкой в Python

Я загружаю целый каталог с веб-сервера. Все работает нормально, но я не могу понять, как получить размер файла до загрузки, чтобы сравнить, был ли он обновлен на сервере или нет. Можно ли это сделать так же, как если бы я загружал файл с FTP-сервера?

import urllib
import re

url = "http://www.someurl.com"

# Download the page locally
f = urllib.urlopen(url)
html = f.read()
f.close()

f = open ("temp.htm", "w")
f.write (html)
f.close()

# List only the .TXT / .ZIP files
fnames = re.findall('^.*<a href="(\w+(?:\.txt|.zip)?)".*$', html, re.MULTILINE)

for fname in fnames:
    print fname, "..."

    f = urllib.urlopen(url + "/" + fname)

    #### Here I want to check the filesize to download or not #### 
    file = f.read()
    f.close()

    f = open (fname, "w")
    f.write (file)
    f.close()

@Jon: спасибо за быстрый ответ. Это работает, но размер файла на веб-сервере немного меньше, чем размер загруженного файла.

Примеры:

Local Size  Server Size
 2.223.533  2.115.516
   664.603    662.121

Это как-то связано с преобразованием CR/LF?

Комментарии к вопросу (2)
Решение

Я воспроизвел то, что вы видите:

import urllib, os
link = "http://python.org"
print "opening url:", link
site = urllib.urlopen(link)
meta = site.info()
print "Content-Length:", meta.getheaders("Content-Length")[0]

f = open("out.txt", "r")
print "File on disk:",len(f.read())
f.close()

f = open("out.txt", "w")
f.write(site.read())
site.close()
f.close()

f = open("out.txt", "r")
print "File on disk after download:",len(f.read())
f.close()

print "os.stat().st_size returns:", os.stat("out.txt").st_size

Выводит это:

opening url: http://python.org
Content-Length: 16535
File on disk: 16535
File on disk after download: 16535
os.stat().st_size returns: 16861

Что я здесь делаю неправильно? Является ли os.stat () .st_size не возвращающим правильный размер?


Редактировать: Хорошо, я понял, в чем проблема:

import urllib, os
link = "http://python.org"
print "opening url:", link
site = urllib.urlopen(link)
meta = site.info()
print "Content-Length:", meta.getheaders("Content-Length")[0]

f = open("out.txt", "rb")
print "File on disk:",len(f.read())
f.close()

f = open("out.txt", "wb")
f.write(site.read())
site.close()
f.close()

f = open("out.txt", "rb")
print "File on disk after download:",len(f.read())
f.close()

print "os.stat().st_size returns:", os.stat("out.txt").st_size

это выводит:

$ python test.py
opening url: http://python.org
Content-Length: 16535
File on disk: 16535
File on disk after download: 16535
os.stat().st_size returns: 16535

Убедитесь, что вы открываете оба файла для двоичного чтения / записи.

// open for binary write
open(filename, "wb")
// open for binary read
open(filename, "rb")
Комментарии (3)

Используя метод возвращаемого объекта info(), вы можете получить различную информацию о полученном документе. Пример захвата текущего логотипа Google:

>>> import urllib
>>> d = urllib.urlopen("http://www.google.co.uk/logos/olympics08_opening.gif")
>>> print d.info()

Content-Type: image/gif
Last-Modified: Thu, 07 Aug 2008 16:20:19 GMT  
Expires: Sun, 17 Jan 2038 19:14:07 GMT 
Cache-Control: public 
Date: Fri, 08 Aug 2008 13:40:41 GMT 
Server: gws 
Content-Length: 20172 
Connection: Close

Это диктант, поэтому, чтобы получить размер файла, вы делаете urllibobject.info()['Content-Length'].

print f.info()['Content-Length']

А чтобы получить размер локального файла (для сравнения), вы можете использовать команду os.stat():

os.stat("/the/local/file.zip").st_size
Комментарии (2)

Размер файла передается в заголовке Content-Length. Вот как получить его с помощью urllib:

>>> site = urllib.urlopen("http://python.org")
>>> meta = site.info()
>>> print meta.getheaders("Content-Length")
['16535']
>>>
Комментарии (0)

Также, если сервер, к которому вы подключаетесь, поддерживает его, посмотрите на Etags и заголовки If-Modified-Since и If-None-Match.

Их использование позволит воспользоваться правилами кэширования веб-сервера и вернуть код состояния 304 Not Modified, если содержимое не изменилось.

Комментарии (0)

Решение на основе [запрашивает][1] с использованием HEAD вместо GET (также печатает заголовки HTTP):


#!/usr/bin/python
# display size of a remote file without downloading

from __future__ import print_function
import sys
import requests

# number of bytes in a megabyte
MBFACTOR = float(1 

> $ python filesize-remote-url.py https://httpbin.org/image/jpeg
>     ...
> Длина содержимого: 35588
> РАЗМЕР ФАЙЛА (МБ): 0,03 МБ

  [1]: http://python-requests.org
Комментарии (0)

В Python3:

>>> import urllib.request
>>> site = urllib.request.urlopen("http://python.org")
>>> print("FileSize: ", site.length)
Комментарии (1)

Для подхода python3 (проверен на 3.5) я бы порекомендовал:

with urlopen(file_url) as in_file, open(local_file_address, 'wb') as out_file:
    print(in_file.getheader('Content-Length'))
    out_file.write(response.read())
Комментарии (0)