Problem Solution Discussion Serving Query Results for Download

body html The first t wo links t o banner.py are ident ical. What youll probably find when you request t his page is t hat your browser will not ice t hat fact , send only a single request t o t he web server, and use t he im age t hat is ret urned where bot h links appear in t he page. As a result , t he first t w o im ages displayed in t he page will be ident ical. The second t wo links t o banner.py show how t o solve t his problem . The links include som e ext ra fluff at t he end of t he URLs t hat m ake t hem look different . banner.py doesnt use t hat inform at ion at all, but m aking t he links look different fools t he browser int o sending t wo im age request s. The result is t hat t he second t wo im ages will differ from each ot her—unless banner.py happens t o random ly select t he sam e im age bot h t im es, of course.

17.9.4 See Also

I f you run a version of MySQL older t han 3.23.2, t he ORDER BY RAND clause used in t he im age- select ion query will fail. See Recipe 13.8 for a workaround.

17.10 Serving Query Results for Download

17.10.1 Problem

You want t o send dat abase inform at ion t o a browser for downloading rat her t han for display.

17.10.2 Solution

Unfort unat ely, t heres no good way t o force a download. A browser will process inform at ion sent t o it according t o t he Content-Type: header value, and if it has a handler for t hat value, it will t reat t he inform at ion accordingly. However, you m ay be able t o t rick t he browser by using a generic cont ent t ype for which it s unlikely t o have a handler.

17.10.3 Discussion

Earlier sect ions of t his chapt er discuss how t o incorporat e t he result s of dat abase queries int o web pages, t o display t hem as paragraphs, list s, t ables, or im ages. But what if you want t o produce a query result t hat t he user can download t o a file inst ead? I t s not difficult t o generat e t he response it self: send a Content-Type: header preceding t he inform at ion, such as textplain for plain t ext , imagejpeg for a JPEG im age, or applicationpdf or applicationmsexcel for a PDF or Excel docum ent . Then send a blank line and t he cont ent of t he query result . The problem is t hat t heres no way t o force t he browser t o download t he inform at ion. I f it knows what t o do wit h t he response based on t he cont ent t ype, it will t ry t o handle t he inform at ion as it sees fit . I f it knows how t o display t ext or im ages, it will. I f it t hinks it s supposed t o give a PDF or Excel docum ent t o a PDF viewer or t o Excel, it will. Most browsers allow t he user t o select a download explicit ly for exam ple, by right - clicking or cont rol- clicking on a link , but t hat s a client - side m echanism . You have no access t o it on t he server end. About t he only t hing you can do is t ry t o fool t he browser by faking t he cont ent t ype. The m ost generic t ype is applicationoctet-stream . Most users are unlikely t o have any cont ent handler specified for it , so if you send a response using t hat t ype, it s likely t o t rigger a download by t he browser. The disadvant age of t his, of course, is t hat t he response cont ains a false indicat or about t he t ype of inform at ion it cont ains. You can t ry t o alleviat e t his problem by suggest ing a default filenam e for t he browser t o use when it saves t he file. I f t he filenam e has a suffix indicat ive of t he file t ype, such as .t xt , .j pg, .pdf, or .xls, t hat m ay help t he client or t he operat ing syst em on t he client host det erm ine how t o process t he file. To suggest a nam e, include a Content-Disposition: header in t he response t hat looks like t his: Content-disposition: attachment; filename= suggested_name The follow ing PHP script , download.php, dem onst rat es one way t o produce downloadable cont ent . When first invoked, it present s a page cont aining a link t hat can be select ed t o init iat e t he download. The link point s back t o download.php but includes a download param et er. When you select t he link, it reinvokes t he script , which sees t he param et er and responds by issuing a query, ret rieving a result set , and sending it t o t he browser for downloading. The Content-Type: and Content-Disposition: headers in t he response are set by invoking t he header funct ion. This m ust be done before t he script produces any ot her out put , or header will have no effect . ?php download.php - retrieve result set and send it to user as a download rather than for display in a web page include Cookbook.php; include Cookbook_Webutils.php; title = Result Set Downloading Example; If no download parameter is present, display instruction page if get_param_val download { construct self-referential URL that includes download parameter url = get_self_path . ?download=1; ? html head title?php print title; ?title head body bgcolor=white p Select the following link to commence downloading: a href=?php print url; ?downloada p body html ?php exit ; } end of if The download parameter was present; retrieve a result set and send it to the client as a tab-delimited, newline-terminated document. Use a content type of applicationoctet-stream in an attempt to trigger a download response by the browser, and suggest a default filename of result.txt. conn_id = cookbook_connect ; query = SELECT FROM profile; if result_id = mysql_query query, conn_id die Cannot execute query\n; header Content-Type: applicationoctet-stream; header Content-Disposition: attachment; filename=\result.txt\; while row = mysql_fetch_row result_id print join \t, row . \n; mysql_free_result result_id; mysql_close conn_id; ? download.php uses a couple of funct ions we havent covered yet . get_self_path ret urns t he script s own pat hnam e. This is used t o const ruct a URL t hat point s back t o t he script and t hat includes a download param et er. get_param_val is used t o det erm ine whet her t hat param et er is present . These funct ions are included in t he Cookbook_Webut ils.php file and are discussed furt her in Recipe 18.2 and Recipe 18.6 . Anot her possibilit y for producing downloadable cont ent is t o generat e t he query result , writ e it t o a file on t he server side, com press it , and send t he result t o t he browser. The browser will likely run som e kind of uncom press ut ilit y t o recover t he original file.

Chapter 18. Processing Web Input with MySQL

Sect ion 18.1. I nt roduct ion Sect ion 18.2. Creat ing Form s in Script s Sect ion 18.3. Creat ing Single- Pick Form Elem ent s from Dat abase Cont ent Sect ion 18.4. Creat ing Mult iple- Pick Form Elem ent s from Dat abase Cont ent Sect ion 18.5. Loading a Dat abase Record int o a Form Sect ion 18.6. Collect ing Web I nput Sect ion 18.7. Validat ing Web I nput Sect ion 18.8. Using Web I nput t o Const ruct Queries Sect ion 18.9. Processing File Uploads Sect ion 18.10. Perform ing Searches and Present ing t he Result s Sect ion 18.11. Generat ing Previous- Page and Next - Page Links Sect ion 18.12. Generat ing Click t o Sort Table Headings Sect ion 18.13. Web Page Access Count ing Sect ion 18.14. Web Page Access Logging Sect ion 18.15. Using MySQL for Apache Logging