Q:

How to create and download a csv file from perl script

I can create a CSV file easily enough:
use Text::CSV_XS;
my $filename = "export.csv";
my $fh;
my $csv = Text::CSV_XS->new ({ binary => 1 });
$csv->eol ("\r\n");

my @rows = ();
push @rows, ['Col1','Col2','Col3'];
push @rows, ['a', 'b', 'c'];
push @rows, ['d', 'e', 'f'];

open $fh, ">:encoding(utf8)", $filename or die "$filename: $!"; 
$csv->print ($fh, $_) for @rows;
close $fh or die "$filename: $!"; 

However if I try to run this same code as a CGI script through a web browser the downloaded csv file is blank.  
use strict;
use warnings;
use CGI;
use Text::CSV_XS;

my $filename = "export.csv";
print "Content-Type:application/x-download\n";
print "Content-Disposition: attachment; filename=$filename\n";
print "\n";

my $fh;
my $csv = Text::CSV_XS->new ({ binary => 1 });
# Specify newline as CR+LF
$csv->eol ("\r\n");

my @rows = ();
push @rows, ['Col1','Col2','Col3'];
push @rows, ['a', 'b', 'c'];
push @rows, ['d', 'e', 'f'];

open $fh, ">:encoding(utf8)", $filename or die "$filename: $!"; 
$csv->print ($fh, $_) for @rows;
close $fh or die "$filename: $!"; 

This code is trying to write the file to disk.  The file written does not appear to be the same file downloaded.  I don't want a file written to disk.  Is there any way to create this file in memory then set headers for download? 
Thank you in advance for any help you can provide. 

A:

As you can see from the two headers that you print, in a CGI program any data that you want sent back to the client (e.g. a browser) should be just printed to STDOUT. 
So I think your fix is as simple as changing:
$csv->print ($fh, $_) for @rows;

to print to STDOUT instead:
$csv->print (STDOUT, $_) for @rows;

You can also remove any code that is involved in handling the file that you now no longer use.