Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,
I have some problem while downloading a file from my server. My code works fine. But downloaded file format is not correct.
My code is as follows .. This code will download a .txt file from server to client machine.
$target_file="filepath"; print "Content-Type: application/x-unknown\n"; print "Content-Disposition: attachment; filename=$flid\n\n"; $output_file = read_file($target_file); print $output_file; sub read_file { local($fname) = @_; local($content); open(FILE, "<$fname") || print "cannot open ".$!; while(<FILE>) { $content .= $_; } close(FILE); return $content; }

and file content is stored in a .txt file and looks like
vy01hc jy02vl hr80je tx92fs qs13kj kk96bg bw95oz st81lv zh64yz vg27tp

but downloded file content in a single line and some extra character in between each line.
Please provide a guideline to solve this problem.
Thanks
sur

Replies are listed 'Best First'.
Re: Downloading file
by Corion (Patriarch) on Feb 07, 2004 at 10:59 UTC

    My guess from your (vague) description is, that somehow the line endings get mushed up in the transfer. The simplest way in your case would be to add

    binmode FILE;

    in your read_file subroutine, and see if that helps.

    Are you sure that your file looks OK on the source side? Are you sure that your download program does not mess with the file as it is written? Windows and Unix have different concepts of "text files", so that might be a problem as well - did you copy the file manually from one machine to another and see if you have the same problems?

      don't forget binmode STDOUT!!!
        Hi,
        Thanks for your valuable information.
        The problem is that while writing a file in server, each data stored in an array will write into the file and "\n" is used to separate each line. I think that's why i couldn't get the proper file.
        writing content in a file, i used this code
        open (FL,"+<file.txt") foreach $ans(@arr) { print FL $ans."\n"; } close FL;
        Is there any way to write content line by line without appending "n"
        Waiting for your suggestion
        Thanks, Sur
Re: Downloading file
by Roger (Parson) on Feb 07, 2004 at 11:36 UTC
    Corion, CountZero and Anonymous Monk are all correct about turining on binmode for input stream and STDOUT. The following is how I would do something similar, it uses the File::Basename to extract the basename from a given path, open and read the file using IO::File, and output compliant header using CGI.

    use strict; use warnings; use File::Basename; use IO::File; use CGI; binmode STDOUT; my $target_file = "/path/to/target_file.dat"; my $f = new IO::File "$target_file", "r" or die; my $file = do { local $/; binmode $f; <$f> }; my $cgi = new CGI; print $cgi->header( -type => 'application/x-unknown', -attachment => basename($target_file) ), $file;

Re: Downloading file
by CountZero (Bishop) on Feb 07, 2004 at 11:20 UTC
    Everything will depend on the machine you are running this script on. UNIX/LINUX, Windows and Mac all have different ideas on what is a text file and esp. how to end each line. Hence you should use binmode both on reading and writing your file in order to avoid the line-endings being "transformed".

    Still if your source file resides on a UNIX system and the client downloads it to a Windows machine, chances are that he will still have problems in reading the file as it will have UNIX-style line-endings. Sadly, there is nothing you can do about that as you do not control the world outside your server!

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law