Web bidez fitxategi bat deskargatu, zatika
Azalpenik behar ez dutenentzat:
1 import urllib2 2 import io 3 from PIL import Image 4 5 def identify_image(url,chunk=5000, max_download=5000000): 6 current_byte = 0 7 end_byte = chunk-1 8 stream = io.BytesIO() 9 image = None 10 11 while image is None: 12 headers = { 13 'Range': 'bytes=%s-%s' % (current_byte, end_byte) 14 } 15 req = urllib2.Request(url, headers=headers) 16 print "Downloading chunk: %s" % headers['Range'] 17 response = urllib2.urlopen(req) 18 if response.headers['Content-Type'][:5] != 'image': 19 raise TypeError("Not supported image type: Content-Type") 20 stream.seek(0,2) #bukaerara goaz 21 stream.write(response.read()) 22 stream.seek(0) 23 try: 24 image = Image.open(stream) 25 except IOError: 26 if int(response.headers['Content-Length']) < chunk: 27 raise TypeError("Not supported image type: unknown file") 28 current_byte += chunk 29 end_byte += chunk 30 if end_byte > max_download: 31 raise TypeError("Not supported image type: Max download") 32 33 return (image.size, image.format)
Imaginatu: web formulario baten bidez erabiltzaileari irudi baten url-a eskatzen diozu, gero zure webgunean erakusteko. Gainera irudi horren informazioa gorde nahi duzu: irudi mota eta tamaina.
- Hau izan daiteke modu sinplena::
>>> import urllib2 >>> from PIL import Image >>> bat = urllib2.urlopen('http://www.gisa-elkartea.org/hasiera/1/1/katua_etzanda.jpg/image') >>> bi = io.BytesIO(bat.read()) >>> im = Image.open(bi) >>> im.size (231, 184) >>> im.format 'JPEG'
Gauza arraro bakarra BytesIO erabiltzearena da, Image.open funtzioak seek funtzioa behar du, eta urlopen-ek ematen diguna ez duenez BytesIO bat erabili behar dugu.
Honek arazo bat du: erabiltzaile gaizto batek izugarri handia den fitxategi bat bidaltzea. Kasu honetan zerbitzariak fitxategi osoa deskargatuko luke, memoria erabat kontsumituz.
Konponbide moduan, fitxategiaren hasierako zati txiki bat bakarrik eskuratu dezakegu. Horretarako HTTP protokoloaren Range goiburukoa erabiliko dugu (12-15 lerroak).
Hasierako zati horretan erantzunaren Content-Type-a begiratu dezakegu; irudia ez bada ez dugu jarraituko (19 lerroa).
Hasierako zati hau PIL bidez egiaztatzen saiatzen gara (24 lerroan); ezezaguna bada IOError salbuespena abiaraziko du. Kasu honetan fitxategiaren hurrengo zatia eskatzen dugu.
Zati berri hau BytesIO-ra gehitu behar dugu. Ezin dugu ziurtatu PIL-ek osorik irakurri duenik, beraz lehenbizi irakurketa kurtsorea bukaerara eramaten dugu, gero jaso dugun zati berria gehitu eta azkenik kurtsorea berriro hasierako puntura eramaten dugu (20-22 lerroak).
Irakurri dugun zatia oraindik nahikoa ez bada eta azkenekoa bada, hau da, eskatu ditugun byte baino gehiago jaso baldin baditugu salbuespena abiarazten dugu (26 lerroa). Berdin deskargatzeko muga gainditu baldin badugu (30 lerroan).
Adibide batzuk:
>>> url = 'http://www.gisa-elkartea.org/hasiera/1/1/katua_etzanda.jpg/image' >>> # Saiatu 500 byte irakurriz >>> try: >>> print deskargatu(url, chunk=500) >>> except TypeError as e: >>> print e Downloading chunk: bytes=0-499 ((231, 184), 'JPEG') >>> # Saiatu 50 byte bakarrik irakurriz, 200 baino gutxiago >>> try: >>> print deskargatu(url, chunk=50, max_download=200) >>> except TypeError as e: >>> print e Downloading chunk: bytes=0-49 Downloading chunk: bytes=50-99 Downloading chunk: bytes=100-149 Downloading chunk: bytes=150-199 Not supported image type: Max download >>> # Saiatu 50 byte bakarrik irakurriz, muga handiarekin >>> try: >>> print deskargatu(url, chunk=50, max_download=5000) >>> except TypeError as e: >>> print e Downloading chunk: bytes=0-49 Downloading chunk: bytes=50-99 Downloading chunk: bytes=100-149 Downloading chunk: bytes=150-199 Downloading chunk: bytes=200-249 Downloading chunk: bytes=250-299 Downloading chunk: bytes=300-349 ((231, 184), 'JPEG')