在PHP中强制文件下载 - 在Joomla框架内

Emm*_*myS 6 php joomla download

我有一些PHP代码在数据库上运行查询,将结果保存到csv文件,然后允许用户下载文件.问题是,csv文件包含围绕实际csv内容的页面HTML.

我已经在这里阅读了所有相关问题,包括这一个.不幸的是我的代码存在于Joomla中,所以即使我尝试重定向到只包含标题的页面,Joomla也会自动用自己的导航代码包围它.这只发生在下载时; 如果我查看保存在服务器上的csv文件,它不包含HTML.

任何人都可以帮我一个强制下载实际csv文件的方法,因为它在服务器上,而不是浏览器正在编辑它?我尝试过使用标头位置,如下所示:

header('Location: ' . $filename);
Run Code Online (Sandbox Code Playgroud)

但它会在浏览器中打开文件,而不是强制保存对话框.

这是我目前的代码:

//set dynamic filename
$filename = "customers.csv";
//open file to write csv
$fp = fopen($filename, 'w');

//get all data
$query = "select 
   c.firstname,c.lastname,c.email as customer_email, 
   a.email as address_email,c.phone as customer_phone,
   a.phone as address_phone,
   a.company,a.address1,a.address2,a.city,a.state,a.zip, c.last_signin
   from {$dbpre}customers c
   left  join  {$dbpre}customers_addresses a  on c.id = a.customer_id  order by c.last_signin desc";

$votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error());
$counter = 1;
while ($row = mysql_fetch_array($votes,1)) {
    //put header row
    if ($counter == 1){
       $headerRow = array();
       foreach ($row as $key => $val)
          $headerRow[] = $key;
       fputcsv($fp, $headerRow);
    }
    //put data row
    fputcsv($fp, $row);
    $counter++;
}

//close file
fclose($fp);

//redirect to file
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$filename);
header("Content-Transfer-Encoding: binary");
readfile($filename); 
exit;
Run Code Online (Sandbox Code Playgroud)

EDITS Full URL如下所示:

http://mysite.com/administrator/index.php?option=com_eimcart&task=customers
Run Code Online (Sandbox Code Playgroud)

实际的下载链接看起来像这样:

http://mysite.com/administrator/index.php?option=com_eimcart&task=customers&subtask=export
Run Code Online (Sandbox Code Playgroud)

更多编辑 这里是代码所在页面的镜头; 生成的文件仍在拉入子菜单的html.现在是所选链接的代码(导出为CSV)

index.php?option=com_eimcart&task=customers&subtask=export&format=raw
Run Code Online (Sandbox Code Playgroud)

替代文字

现在这里是生成的保存文件的屏幕截图:

替代文字

它在上传过程中收缩,但黄色突出显示的文本是subnav的html代码(列出客户,添加新客户,导出为csv).这就是我的完整代码现在的样子; 如果我能摆脱最后一点的HTML,它将是完美的.

  $fp= fopen("php://output", 'w');

            $query = "select c.firstname,c.lastname,c.email as customer_email, 
                      a.email as address_email,c.phone as customer_phone,
                      a.phone as address_phone,  a.company, a.address1,
                      a.address2,a.city,a.state,a.zip,c.last_signin

                      from {$dbpre}customers c
                      left  join  {$dbpre}customers_addresses a on c.id = a.customer_id  
                      order by c.last_signin desc";

            $votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error());
            $counter = 1;

            //redirect to file
            header("Content-type: application/octet-stream");
            header("Content-Disposition: attachment; filename=customers.csv");
             header("Content-Transfer-Encoding: binary");

            while ($row = mysql_fetch_array($votes,1)) {

                    //put header row
                    if ($counter == 1){
                            $headerRow = array();
                            foreach ($row as $key => $val)
                                    $headerRow[] = $key;

                            fputcsv($fp, $headerRow);
                    }

                    //put data row
                    fputcsv($fp, $row);
                $counter++;
            }

            //close file
            fclose($fp);
Run Code Online (Sandbox Code Playgroud)

BJORN更新

这是代码(我认为)对我有用.在调用操作的链接中使用RAW参数:

index.php?option=com_eimcart&task=customers&subtask=export&format=raw
Run Code Online (Sandbox Code Playgroud)

因为这是程序性的,我们的链接位于名为customers.php的文件中,如下所示:

switch ($r['subtask']){
    case 'add':
    case 'edit':
        //if the form is submitted then go to validation
                include("subnav.php");
        if ($r['custFormSubmitted'] == "true")
            include("validate.php");
        else
            include("showForm.php");
        break;

    case 'delete':
                include("subnav.php");
        include("process.php");
            break;

    case 'resetpass':
                include("subnav.php");
        include("resetpassword");
            break;

    case 'export':
        include("export_csv.php");
            break;


    default:
                include("subnav.php");
        include("list.php");
        break;
}
Run Code Online (Sandbox Code Playgroud)

因此,当用户单击上面的链接时,会自动包含export_csv.php文件.该文件包含所有实际代码:

<?
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=customers.csv");
header("Content-Transfer-Encoding: binary");
$fp= fopen("php://output", 'w');


//get all data
$query = "select 
    c.firstname,c.lastname,c.email as customer_email, 
    a.email as address_email,c.phone as customer_phone,
    a.phone as address_phone,
    a.company,a.address1,a.address2,a.city,a.state,a.zip, c.last_signin

    from {$dbpre}customers c

    left  join  {$dbpre}customers_addresses a  on c.id = a.customer_id  order by c.last_signin desc";


$votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error());
$counter = 1;

while ($row = mysql_fetch_array($votes,1)) {

    //put header row
    if ($counter == 1){
        $headerRow = array();
        foreach ($row as $key => $val)
            $headerRow[] = $key;

        fputcsv($fp, $headerRow);
    }

    //put data row
    fputcsv($fp, $row);
    $counter++;
}

//close file
fclose($fp);
Run Code Online (Sandbox Code Playgroud)

sil*_*lvo 3

这是我刚刚编写的一段示例代码来帮助您。将其用作控制器中的操作方法。

function get_csv() {
        $file = JPATH_ADMINISTRATOR . DS . 'test.csv';

        // Test to ensure that the file exists.
        if(!file_exists($file)) die("I'm sorry, the file doesn't seem to exist.");

        // Send file headers
        header("Content-type: text/csv");
        header("Content-Disposition: attachment;filename=test.csv");

        // Send the file contents.
        readfile($file);
    }
Run Code Online (Sandbox Code Playgroud)

仅此还不够,因为您下载的文件仍将包含周围的 html。要摆脱它并仅接收 csv 文件的内容,您需要在请求中添加 format=raw 参数。就我而言,该方法位于 com_csvexample 组件内部,因此 url 为:

/index.php?option=com_csvexample&task=get_csv&format=raw
Run Code Online (Sandbox Code Playgroud)

编辑

为了避免使用中间文件替代

//set dynamic filename
$filename = "customers.csv";
//open file to write csv
$fp = fopen($filename, 'w');
Run Code Online (Sandbox Code Playgroud)

//open the output stream for writing
//this will allow using fputcsv later in the code
$fp= fopen("php://output", 'w');
Run Code Online (Sandbox Code Playgroud)

使用此方法,您必须在将任何内容写入输出之前移动发送标头的代码。您也不需要调用该readfile函数。