Régebbiek ekkorról: May, 2009

Gzip / Deflate beállítás IIS 6-on

Írta: tcz on May 18, 2009
Uncategorized / Nincsenek hozzászólások

search01“Guglizzad meg, gyermekem” – tanították a nagyok, és én, mint jó diák, így is teszek mindig. Olykor azonban szembesülni kell a zsákutcákkal, amiket az internet sötét démonai építenek nekünk, mint például a Microsoft. Álljon itt egy terképrészlet az útvesztőben rekedteknek. :)

Történt ugyanis, hogy az IIS 6-ot be akartam állítani, hogy a kimenetét GZippel vagy Deflate-tel tömörítve külje annak a kliensnek, amelyik ezt szereti (a Deflate gyorsabb egyébként). Alapvetően Apache+Linux párti vagyok, ezért nem ismertem pontosan a beállítás módját, hát rákerestem. Kaptam is rögtön pár jól kinéző találatot:

Az első rendben is van. A másiknál több furcsaság is felmerül. Itt megadhatjuk, hogy az alapértelmezett .html, .htm és .txt fájlok mellett még milyeneket tömörítsen. Először is: kiterjesztések? WTF? Mennyivel értelmesebb lenne Content-Type-ra szűrni! Másodszor: külön kell statikus és dinamikus tartalmakra beállítani a kiterjesztéseket. Ismét csak WTF??? De nem baj, ez biztos olyan IIS logika, amit én nem érthetek.

Szépen elvégeztem hát az (eredeti microsoftos-technetes!) leírásban leírt teendőket, újraindítottam a webszervert és vártam a gyönyörűszép Content-Encoding response headert. De az csak nem jött.

Beletelt némi időbe, mire kiderítettem, hogy mi a baja. Szóval most mindenkivel megosztom a HELYES módját a beállításnak, ugyanis a technetes leírás ROSSZ. A slusszpoén az, hogy a tömörítendő kiterjesztések listájának elemeit nem szóközzel kell elválasztani, mint ahogy a tutorial írja, hanem CR+LF-fel, ami ugye parancssorból eleve lehetetlen. Így a következőket kell tennünk:

  1. Nyomjuk Windows+R-t (Run/Futtatás)
  2. Írjuk be, hogy cmd (Command Prompt)
  3. Írjuk a parancssorba, hogy issreset /stop, majd enter – ez ideiglenesen lelövi az IIS-t, amíg a konfigot szerkesztjük
  4. Nyissuk meg a %systemroot%\system32\inetsrv könyvtárat, és keressük meg a MetaBase.xml-t – ez tárolja az IIS konfigurációját.
  5. A fájlt texteditorral megnyitva keressük meg a IIsCompressionScheme nevű tageket, melyek a tömörítéstípusok beállításait tartalmazzák, és szerkesszük őket úgy, hogy valahogy így nézzenek ki (vegyük észre a CRLF-eket a HcFileExtensions és HcScriptFileExtensions attribútumban):
    <IIsCompressionScheme	Location ="/LM/W3SVC/Filters/Compression/gzip"
    		HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"
    		HcCreateFlags="1"
    		HcDoDynamicCompression="TRUE"
    		HcDoOnDemandCompression="TRUE"
    		HcDoStaticCompression="TRUE"
    		HcDynamicCompressionLevel="3"
    		HcFileExtensions="html
    			html
    			css
    			js
    			wsdl"
    		HcOnDemandCompLevel="10"
    		HcPriority="1"
    		HcScriptFileExtensions="asp
    			dll
    			exe
    			xml
    			asmx
    			aspx
    			wsdl"
    	>
    </IIsCompressionScheme>

     

  6. A IIsCompressionSchemes tag többi, általános beállítást tartalmazza, nézzük át ezeket is!
  7. Mentés, és issreset /start a Command Prompt-ban

Nagyjából ennyi. Ha a kliensünk rendes Accept-Encoding: gzip, deflate headerrel küldi a requestet, akkor csodaszép tömörített válaszokat kell, hogy kapjunk, amivel átlagban a sávszél 75%-át is megspróroljuk.

Cuppantás.

PHP + GD képkivágás

Írta: tcz on May 13, 2009
Uncategorized / 6 hozzászólás

Nem állítom, hogy az alábbi egy mindennapi probléma egy PHP fejlesztő életében, de magyar nyelvű tutorialból sosem elég, és hátha valaki pont ezt keresi. Ráadásul ihletadónak is tökéletes hasonló problémák megoldásához.

Olykor úgy adódik, hogy egy – mondjuk tartalomfejlesztő által feltöltött – képről le kell vágni a sallangot. Úgy értem a fehér keretet. Nekem például egy webáruház termékfotóit kellett rendbetennem – ezek jellemzően fehér hátterű képek. A feltöltött kép körül lévő nagy üres terület a kisképek (thumbnailek) generálásánál nagyon zavaró volt, mert a terméklistában nem kerültek egy vonalba a termékek szélei.

A megoldást a PHP népszerű képmanipuláló modulja, a GD szállítja. Itt a kód:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
	// betöltjük a képet
	$img=imagecreatefromstring($imgstring);
 
	// beállítjuk a keresés felbontását
	// ennek változtatásával kb. négyzetesen változik a script futási ideje
	$resolution=30;
 
	// az eredeti kép méretei
	$largewidth=imagesx($img);
	$largeheight=imagesy($img);
 
	// a nem "üres" képpontok helyét tartalmazó tömb
	$nonwhites=array("x"=>array(), "y"=>array());
 
	// a felbontássnak megfelelően végigpásztázzuk a képet, és
	// ahol nem fehér pixelt találunk, annak feljegyezzük a helyét
	// tengelyekre bontva
	for ($x=0;$x < $largewidth;$x+=($largewidth/$resolution)) {
		for ($y=0;$y < $largeheight;$y+=($largeheight/$resolution)) {
			// megkérdezzük az adott helyen lévő pixel RGB értékei
			$arr=ImageColorsForIndex($img, ImageColorAt($img, intval($x), intval($y)));
			$arr=array($arr['red'], $arr['green'], $arr['blue']);
 
			// ha az RGB értékek számtani közepe elég alacsony, akkor 
			// nem fehér(szerű) képontról beszélünk, jegyezzük a helyet
			if (AritMid($arr)<245) {
				$nonwhites['x'][]=intval($x);
				$nonwhites['y'][]=intval($y);
			}
		}
	}
 
	// a nem fehér képpontok tengelyekre bontott helye megvan
	// ha ezek minimumát és maximumát vesszük, megvan a kép
	// értékes része - persze egységnyit ráhagyunk minden oldalon
	$crop_coordinates=array(
		"x1"=>max(0,min($nonwhites['x'])-($largewidth/$resolution)),
		"y1"=>max(0,min($nonwhites['y'])-($largeheight/$resolution)),
		"x2"=>min($largewidth,max($nonwhites['x'])+($largewidth/$resolution)),
		"y2"=>min($largeheight,max($nonwhites['y'])+($largeheight/$resolution)),
	);
 
	// ha kell, szélességet és magasságot is számolhatunk
	// kivágáshoz pl. ezeket kell használnunk
	$crop_coordinates['width']=$crop_coordinates['x2']-$crop_coordinates['x1'];
	$crop_coordinates['height']=$crop_coordinates['y2']-$crop_coordinates['y1'];
 
	// tesztként most csak rárajzoljuk a kivágást a képre
	// szép zöldben
	$green=ImageColorClosest($img, 0, 255, 0);
	imagerectangle ($img, $crop_coordinates["x1"], $crop_coordinates["y1"], $crop_coordinates["x2"], $crop_coordinates["y2"], $green);
	imagejpeg($img, "test.jpg", 90);
	echo "<img src='test.jpg' /><br/>";
?>

A kommentek a kódban elég egyértelműek, de azért pár szóban a működésről:

  1. A szkript betölt egy képet, majd ráilleszt egy meghátorozott felbontású képzeletbeli rácsot. 
  2. Megvizsgálja a rács pontjain található pixelek színét, és ha nem elég világosak, akkor megjegyzi a helyüket.
  3. A megjegyzett helyek tengelyenkénti minimumát véve megkapjuk a kép értékes részét.

Az eredmény:

 

Az eredeti kép

Az eredeti kép




A kivágás

A kivágás

 

 

Használjátok egészséggel!

Ez nem gáz?

Írta: tcz on May 09, 2009
Uncategorized / Nincsenek hozzászólások

Kb 2 éve van Google Adsense accountom. (Habár nem használom, nem lehet valami alapítványnak küldeni a kifizetési határ alatti összeget?) Azóta ez az üzenet fogadja azokat, akik a programra jelentkezni kívánnak:

gaz

Ez különben nem iszonyat ciki a Google-nek? Hahó, ez nem a 90-es évek!

A helpben ezt írják:

A számlázási rendszerünkben érvényes, nyomtatásra vonatkozó megkötésekből adódóan csak az ISO-Latin-1 karakterkészletben szereplő karaktereket tudjuk elfogadni. Kérjük, nevének és címének megadására kizárólag az alábbi karaktereket használja. [felsorolás]

Tudom-tudom, számlázási rendszer meg minden, de egy akkora óriás, mint a Google, nem tudja áthidalni ezt? Nem is értem.

Na mindegy, a szifon szerint kezd kisütni a nap (az megvan, hogy Yahooéknál Cegléd=Czegled?). Irány kirándulni!

Hozzávalók egy villámgyors weboldalhoz

Írta: tcz on May 06, 2009
Uncategorized / Nincsenek hozzászólások

bugatti-veyronA sebesség a legfontosabb, megírta Doransky is. Ha a webet építed, nyilván tisztában vagy ezzel, és azzal is, hogy milyen eszközökkel kerülheted el, hogy a felhasználók (akár több szint oldalmélységben is) a lassúság miatt hagyják ott a weboldalad.

Megpróbálok összegyűjtani néhány tippet, hátha valamelyiket még nem ismered, vagy csak egy jó checklistként használhatod munka közben.

  1. Használj minél kevesebb képet! Próbálj mindent CSS-sel megoldani, ha kell, tisztíts a dizájnon! A képeket lehet a leglassabban megjeleníteni. Doglas Bowman megmutatta, hogy nem létezik lehetetlen.
  2. Ha már képeket használsz, tömöríts okosan! A GIF/JPEG/PNG nagyon fontos kérdés lehet. Ajánlat: GIF vs JPG
  3. Még mindig képek: használj sprite-okat, vagyis amit csak lehet, tegyél rá egy képfájlra, és CSS-sel igazítsd! Ez rollovernél kötelező, dizájnelemeknél ajánlott, de a tartalmi részeknél sem tilos.
  4. Kevesen ismerik az képek HTML-be ágyazásának technikáját. Kis méretű képeknél és statikus tartalomnál érdemes megfontolni, ezzel is csökkentve a HTTP kérések számát. Nézd meg a forrást! 
  5. Kerüld el a Flash tartalmakat!
  6. Használj template kezelőket! A Smarty például jelentősen gyorsíthat az oldalad megjelenítésén.
  7. Tömörítsd az oldal kimenetét (gzip/deflate). Ez PHP-nál ennyi a script tetejére:
    <? ob_start(”ob_gzhandler”); ?>
    De  van rá Smarty plug-in is. Ha ügyes vagy, akár egy javascript kódot vagy css-t és zipelhetsz az Apache megfelelő beállításaival
  8. Ismerkedj meg olyan cache-elő megoldásokkal, mint például a memcached! Ez a gyakran használt lekérdezéseket eltárolja a memóriában, és ezeket onnan tölthetjük be újra.
  9. Triviális, de a PHP “echo” gyorsabb, mint a “print”, mert nincs visszatérési értéke. Sok kicsi sokra megy alapon felejtsd el a printet!
  10. Adatbázis lekérdezésnél sokszor lustaságból SELECT *-ot írnunk, tehát az összes tábla összes mezőjét lekérdezzük. Ha leszűkíted a mezőket arra, amelyekre szükséged van, akkor gyorsíthatsz egy bonyolult lekérdezésen és a saját életed is egyszerűsítheted.
  11. Minden mezőt indexelj, amit csak tudsz! Egy weboldal klasszikus adatbázis művelete a SELECT, a tömeges beszúrás avgy update nem jellemző, így szinte mindent indexelhetünk, amit tudunk, és amire valaki is akarjuk rendzeni a táblát vagy szűrni rá.
  12. Ne mindig ragaszkodj a relációkhoz egy adatbázisnál! Ismerkedj a key-value adatbázistáblákkal, bizonyos esetekben sokat gyorsíthatsz ezzel is. Bővebben…
  13. Adatbázis lekérdezésnél a fetch_row jóval gyorsabb lehet, mint a fetch_array. Így ha tudod a lekérdezett mezők sorrendjét, akkor inkább használd ezt! A fetch_array és fetch_object között nincs számottevő különbség.
  14. Az adatbázisból generált menüket (például termékfa vagy legutóbbi cikkek) generáld le egyszer, és utána egy adatbázistáblában tárold úgy, ahogy egy az egyben beszúrhatod a layoutba! Írj egy függvényt ennek frissítésére, ha változik a termékhalmaz vagy írsz egy új cikket, és csak ezekben az esetekben frissíts!
  15. Ha van keresés a weboldaladon, a találatokat mentsd el, és bizonyos időn belül (mondjuk 12 óra) ezt töltsd be ugyanarra a keresőkifejezésre!
  16. Érdemes a különböző javascript fájlokat összeszervezni egybe, így csak egy HTTP kérés kell az összes kód letöltéséhez. Különválasztani azonban fontos a HTML kódtól, hiszen ez kevésbbé változik, jobban gyorsítótárazható.
  17. Ne spórolj a hardveren! A Raid 1+0 sokat gyorsíthat a lemezelérésen, és persze minél több RAM mindenek előtt!
  18. Használjunk AJAX-ot amihez csak lehet! Főleg űrlapok tartalmának ellenőrzésére nagyszerű, de tartalmi részeket is cserélgessünk bátran AJAX-szal!

Nekem hirtelen ennyi jutott eszembe, kommentben várom a ti tippjeiteket!

PHP-ből Excel Smarty-val

Írta: tcz on May 05, 2009
Uncategorized / 3 hozzászólás

1149083_pear_2

Rühellem a PEAR-t. Nem tehetek róla, hánynom kell tőle. Van egy csomó hasznos PEAR modul, ami sokszor jól is jönne, de annyira ostobán van az egész PEAR csomag disztributálva, hogy nem szívesen dolgozok vele.

PHP-ből Excelt csinálni az üzleti életben egy eléggé kommerszt feladat, nagyon sokszor jól jön egy exceles árlista például. Ha valamit megtanultam az üzleti IT-ról az az, hogy Excel alapokon nyugszik. :) Márpedig ehhez a feladathoz a legtöbben PEAR-hez nyúlnának, ha nem olvasnák el az alábbi kis szösszenetet.

A címet megpillantva leeshetett, hogy a népszerű templatekezelőt fogjuk használni a feladathoz, de akik nem ismerik (vagy nem használják???) a Smarty-t, azok se ijedjenek meg – idősek is elkezdhetik.

Szóval Excel. Meglepő, de a Microsoft az Office XP óta támogatja az Excel fájlok valid XML-ben történő mentését és megnyitását. Miért meglepő? Mert a Microsoft nem arról híres, hogy szereti és követi a nyílt szabványokat. Esetünkben azonban egészen csinos kis XML névteret hozott össze.

XML-es XLS?

Így néz ki egy fincsi XML alapú Excel:

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">
 
<Worksheet ss:Name="Work-Shit">
<Table>
<Column ss:AutoFitWidth="1" />
<Row>
<Cell><Data ss:Type="String">I</Data></Cell>
<Cell><Data ss:Type="String">love</Data></Cell>
<Cell><Data ss:Type="String">Microsoft</Data></Cell>
<Cell><Data ss:Type="String">:-)</Data></Cell>
</Row>
</Table>
</Worksheet>
 
</Workbook>

Nem akarom különösebben megmagyarázni a tagek jelentését, aki mélyebben beleásná magát a dologba, annak itt van az MSDN. Ebből a kis XML-ből csinálunk egy Smarty template-et, mégpedig úgy, hogy a cellákat a templatekezelő dobálja ki az átadott tömbök alapján. Valahogy így. (Link javítva.)

Aki letölti a fájlt, az láthatja, hogy van benne még például egy Styles tag a fentiekhez képest, itt adhatunk formázást is a celláknak (kb. úgy működik, mint egy stylesheet). A Data tag Type attribútima pedig azt mondja meg, hogy az adott cella szöveget, számot, logikai értéket vagy disznótorost tárol. A fenti linken többet ír erről a Microsoft.

Most már csak annyi a dolgunk, hogy létrehozzuk a PHP kódot, ami innen-onnan kapott adatokból legyártja azt a két dimenziós tömböt, amit az ügyes kis Smarty megjelenít.

PHP+Smarty+XML+Excel-Pear

Egy Excel cella reprezentálására egy osztályt fogunk használni, amely tárolja a cella értékét, stílusát, típusát:

1
2
3
4
5
6
7
8
9
10
11
class ExCell { // :-)
	public $value;
	public $style;
	public $type;
 
	function __construct($value, $type="String", $style=null) {
		$this->value=$value;
		$this->style=$style;
		$this->type=$type;
	}
}

Alapértelmezésben szövegként tárolunk mindent. Most már csak ezeket a kis ExCelleket kell belepakolni egy két dimenziós tömbbe, amit szeretettel átadhatunk a Smartynak.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function MakeExcel() {
	// ezeket singletonba szerveztük, érdemes!
	$db = DB::Get();
	$smarty=MySmarty::Get();
 
	$q=$db->Query("SELECT becenev AS cikkszam, natur_francia_ar AS ar FROM konnyuveru_nok");
 
	$cells=array();
 
	while ($r=mysql_fetch_array($q)) {
		$newline=array();
		$newline[]=new ExCell($r['cikkszam']);
		$newline[]=new ExCell($r['ar'], "Number", "forint");
 
		$cells[]=$newline;
	}
 
	$smarty->assign('worksheetname', "Nők");
	$smarty->assign('cells', $cells);
 
	header("Content-Type: application/vnd.ms-excel; charset=UTF-8");
	header("Content-Disposition: attachment; filename=\"nok_arlista.xls\"");
 
	$smarty->Build("excel.tpl");
}

Hát ennyi. Jó éjszakát gyerekek!