How do I send a file to the user?
Hi I want to do the following: The users fills out a form and depending on that data an excel export is generated. The user should be prompted to store/open the file. The code to create the excel data is working fine. But I don't know how to do the file sending stuff? Is hook_file_download the right way to go? If yes, after I have the excel file content stored in a variable how does it get to the implementation of hook_file_download? TIA Ernst
Ernst Plüss wrote:
Hi
I want to do the following: The users fills out a form and depending on that data an excel export is generated. The user should be prompted to store/open the file.
The code to create the excel data is working fine.
But I don't know how to do the file sending stuff? Is hook_file_download the right way to go? If yes, after I have the excel file content stored in a variable how does it get to the implementation of hook_file_download?
TIA Ernst
no, thats not the right function. you just need to send the right http headers and then print out your excel data. see http://us2.php.net/header. you can use that function directly. no benefit to going through drupal here.
On 2/1/07, Moshe Weitzman <weitzman@tejasa.com> wrote:
no, thats not the right function. you just need to send the right http headers and then print out your excel data. see http://us2.php.net/header. you can use that function directly. no benefit to going through drupal here.
That's right, setting the HTTP headers is the key to doing this. The most common way to force a file download prompt is to set the 'content-disposition' header, which you can do in PHP like this: header('Content-Disposition: attachment; filename="downloaded.pdf"'); However, this is not officially part of the HTTP standard (although it is widely supported), and it has issues with Internet Explorer. See http://www.hanselman.com/blog/TheContentDispositionSagaControllingTheSuggest... for more details. Cheers, Jaza.
See also: http://api.drupal.org/api/5/function/drupal_set_header On 1/31/07, Jeremy Epstein <jazepstein@gmail.com> wrote:
On 2/1/07, Moshe Weitzman <weitzman@tejasa.com> wrote:
no, thats not the right function. you just need to send the right http headers and then print out your excel data. see http://us2.php.net/header. you can use that function directly. no benefit to going through drupal here.
That's right, setting the HTTP headers is the key to doing this. The most common way to force a file download prompt is to set the 'content-disposition' header, which you can do in PHP like this:
header('Content-Disposition: attachment; filename="downloaded.pdf"');
However, this is not officially part of the HTTP standard (although it is widely supported), and it has issues with Internet Explorer. See
http://www.hanselman.com/blog/TheContentDispositionSagaControllingTheSuggest... for more details.
Cheers, Jaza.
-- Regards, Johan Forngren johan@forngren.com :: http://johan.forngren.com/
On 1/31/07, Ernst Plüss <ernst.pluess@gmail.com> wrote:
I want to do the following: The users fills out a form and depending on that data an excel export is generated. The user should be prompted to store/open the file.
The code to create the excel data is working fine.
But I don't know how to do the file sending stuff? Is hook_file_download the right way to go? If yes, after I have the excel file content stored in a variable how does it get to the implementation of hook_file_download?
Well if you're actually generating a file file_tranfer() would do the trick. Though even if you're streaming something the code would give you good starting point. http://api.drupal.org/api/HEAD/function/file_transfer Good luck, andrew
See the module profile CSV for one way of doing this.
Thanks for your answers guis! What I did so far: 1. generated the content of the excel file and store it in a variable 2. sent the appropriate http-header information 3. sent the excel file with print $exel_contet; First this works fine for the user, he gets the download popup and stores the file. But the next time the user clicks on a drupal link he gets this: warning: Cannot modify header information - headers already sent by (output started at C:\apachefriends\xampp\htdocs\istl\modules\simplenews\simplenews.module:1729) in C:\apachefriends\xampp\htdocs\istl\includes\common.inc on line 269. I'm sure to not have any spaces sent before my header information is sent. But somehow drupal isn't happy that I'm sending header informations myself. This is my code: if ($where && $where_tid) { $query = 'SELECT DISTINCT s.mail, s.name FROM {sn_subscriptions} s INNER JOIN {sn_snid_tid} t ON s.snid = t.snid WHERE ('.$where.') AND ('.$where_tid.')'; $result = db_query($query); while ($mail = db_fetch_object($result)) { $mails[] = $mail; } } $data = "Name\tEmail\n"; foreach($mails as $entry) { $line = simplenews_clean_value($entry->name); $line .= simplenews_clean_value($entry->mail); $data .= trim($line)."\n"; } $data = str_replace("\r","",$data); header("Content-type: application/x-msdownload"); header("Content-Disposition: attachment; filename=news_export.xls"); header("Pragma: no-cache"); header("Expires: 0"); print "$data"; Any ideas? TIA Ernst
Try http://api.drupal.org/api/5/function/drupal_set_header On 2/1/07, Ernst Plüss <ernst.pluess@gmail.com> wrote:
Thanks for your answers guis!
What I did so far: 1. generated the content of the excel file and store it in a variable 2. sent the appropriate http-header information 3. sent the excel file with print $exel_contet;
First this works fine for the user, he gets the download popup and stores the file. But the next time the user clicks on a drupal link he gets this:
warning: Cannot modify header information - headers already sent by (output started at
C:\apachefriends\xampp\htdocs\istl\modules\simplenews\simplenews.module:1729) in C:\apachefriends\xampp\htdocs\istl\includes\common.inc on line 269.
I'm sure to not have any spaces sent before my header information is sent. But somehow drupal isn't happy that I'm sending header informations myself.
This is my code: if ($where && $where_tid) { $query = 'SELECT DISTINCT s.mail, s.name FROM {sn_subscriptions} s INNER JOIN {sn_snid_tid} t ON s.snid = t.snid WHERE ('.$where.') AND ('.$where_tid.')'; $result = db_query($query); while ($mail = db_fetch_object($result)) { $mails[] = $mail; } }
$data = "Name\tEmail\n"; foreach($mails as $entry) { $line = simplenews_clean_value($entry->name); $line .= simplenews_clean_value($entry->mail); $data .= trim($line)."\n"; } $data = str_replace("\r","",$data); header("Content-type: application/x-msdownload"); header("Content-Disposition: attachment; filename=news_export.xls"); header("Pragma: no-cache"); header("Expires: 0"); print "$data";
Any ideas? TIA Ernst
-- Regards, Johan Forngren johan@forngren.com :: http://johan.forngren.com/
Having a closer look at http://api.drupal.org/api/5/function/_locale_export_po showed gave me the solution. A die(); after sending out headers and excel data did the job. I don't know exactly why this is needed, my guess is that if it's missing somehow the next time a header is sent php thinks it belongs to the same response and complains because already non header data has been sent. Thanks a lot for your assistance! Ernst
I might be wrong on this one, but I've always been told to never use die() in Drupal, since it stops code from the footer to be run. I recommend you to use <http://api.drupal.org/api/5/function/drupal_set_header> http://api.drupal.org/api/5/function/drupal_set_header to override drupal's headers. OT: Should we write a patch to remove that die()-call? On 2/1/07, Ernst Plüss <ernst.pluess@gmail.com> wrote:
Having a closer look at http://api.drupal.org/api/5/function/_locale_export_po showed gave me the solution.
A die(); after sending out headers and excel data did the job. I don't know exactly why this is needed, my guess is that if it's missing somehow the next time a header is sent php thinks it belongs to the same response and complains because already non header data has been sent.
Thanks a lot for your assistance! Ernst
-- Regards, Johan Forngren johan@forngren.com :: http://johan.forngren.com/
I have no problem with not using die(). I first tried http://api.drupal.org/api/5/function/drupal_set_header without success. The only way to get rid of the "headers already sent" warning was using die(). I think what you say about not using die() is exactly what is necessary if you send a file with additional header information. You have to make sure drupal isn't sending any other header information in the same request later on. So what should I do instead of calling die()? TIA Ernst 2007/2/1, Johan Forngren <johan@forngren.com>:
I might be wrong on this one, but I've always been told to never use die() in Drupal, since it stops code from the footer to be run. I recommend you to use http://api.drupal.org/api/5/function/drupal_set_header to override drupal's headers.
OT: Should we write a patch to remove that die()-call?
On 2/1/07, Ernst Plüss <ernst.pluess@gmail.com > wrote:
Having a closer look at http://api.drupal.org/api/5/function/_locale_export_po showed gave me the solution.
A die(); after sending out headers and excel data did the job. I don't know exactly why this is needed, my guess is that if it's missing somehow the next time a header is sent php thinks it belongs to the same response and complains because already non header data has been sent.
Thanks a lot for your assistance! Ernst
-- Regards, Johan Forngren
johan@forngren.com :: http://johan.forngren.com/
So what should I do instead of calling die()?
The same problem exists with JSON "pages". The solution: // after you're done outputting all your content, run: drupal_page_footer(); exit; Konstantin Käfer – http://kkaefer.com/
participants (7)
-
andrew morton -
Ernst Plüss -
Jeremy Epstein -
Johan Forngren -
Khalid B -
Konstantin Käfer -
Moshe Weitzman