1

I have a script that generates a file for download through ajax. I need to control this request because not everyone should be able to download a file. The process looks like this:

  1. Listen for click event, send ajax request with data to the server
  2. The request is handled, if everything is OK a temporary file is generated with the first line to be the filename and further content is the content of the file to download
  3. Send the URL for the newly generated file back to the ajax function and fill a hidden iframe's src attribute with that endpoint.
  4. When the endpoint is called, a controller method checks if the file exists, opens it and puts the first line to a $filename variable using array_shift and puts the rest of the content to the $content variable,
  5. Set the headers for a download and echo out the $content variable.

Somehow this doesn't work as expected. It's not because of the iframe, because when I visit the URL in the browser Chrome tells me there an ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION error. I'm using Laravel and I don't see where I've set falsly headers?

The download script so far:

public function download($fileId)
{
    $file = $this->tempFilesPath . $fileId;

    if (file_exists($file)) {
        $data         = explode("\n", file_get_contents($file));
        //@unlink($file);

        $fileName  = array_shift($data);
        $content   = implode("\n", $data);

        header('Content-Type: application/force-download');
        header('Content-Disposition: attachment; filename=' . $fileName);

        echo $content;
        exit;
    }
}

Dumping the values of $fileName and $content shows the expected values.

Suggestions? Thanks.

Ben Fransen
  • 10,884
  • 18
  • 76
  • 129
  • Yes there seems to be error with headers. Havent gone through your logic but here is a link to help out http://stackoverflow.com/questions/386845/http-headers-for-file-downloads Also on the same point,might be better just to set document.location to the link, file would be downloaded and not redirected to the download link. – georoot May 01 '16 at 08:45
  • Thanks for your reply, too bad changing the content type to application/octet-stream didn't help. – Ben Fransen May 01 '16 at 08:51

2 Answers2

6

After some extra digging I found a post that writes about this specific error. It was because I was formatting the filename with a date, containing a comma which was upsetting Chrome. Changed the filename convention and it works now. I'll leave the question online if anyone else might run into this behavior later.

For the future solution seekers:

I first named the file $filename = 'download_' . date('d-m-Y, H:i:s') . '.ext', but the comma in the date format was the cause of the problem. Leave it out and you should be one step further to resolving your issue.

Ben Fransen
  • 10,884
  • 18
  • 76
  • 129
3

You could modify your download Method like so:

public function download($fileId) {
    $file     = $this->tempFilesPath . $fileId;

    if (file_exists($file)) {
        //$data           = explode("\n", file_get_contents($file));
        //@unlink($file);
        //$content    = implode("\n", $data);   
        //$fileName   = array_shift($data);
        $size         = @filesize($file);

        //ADD THESE FEW LINES
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');

        //header('Content-Type: application/force-download');
        header('Content-Disposition: attachment; filename=' . $fileId);
        header('Content-Transfer-Encoding: binary');

        //header('Content-Length: ' . $size);

        readfile($file);
        return TRUE;
    }
}
Poiz
  • 7,611
  • 2
  • 15
  • 17