views:

260

answers:

3

Hey gang, I'm trying to convert a legacy php script over to python and not having much luck.

The intent of the script is to serve up a file while concealing it's origin. Here's what's working in php:

<?php
$filepath = "foo.mp3";

$filesize = filesize($filepath);

header("Pragma: no-cache");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

// force download dialog
//header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");

header('Content-Disposition: attachment;filename="'.$filepath.'"');

header("Content-Transfer-Encoding: binary");

#header('Content-Type: audio/mpeg3');
header('Content-Length: '.$filesize);

@readfile($filepath);
exit(0);
?>

When I do the equivilent in Python, I get a download that is zero bytes. Here's what I'm trying:

#!/usr/bin/env python
# encoding: utf-8

import sys
import os
import cgitb; cgitb.enable()

filepath = "foo.mp3" 
filesize = os.path.getsize(filepath)

print "Prama: no-cache"
print "Expires: 0"
print "Cache-Control: must-revalidate, post-check=0, pre-check=0"

print "Content-Type: application/octet-stream"
print "Content-Type: application/download"

print 'Content-Disposition: attachment;filename="'+filepath+'"'

print "Content-Transfer-Encoding: binary"

print 'Content-Length: '+str(filesize)

print  #required blank line

open(filepath,"rb").read()

Can anyone please help me?

+5  A: 

Well, maybe it's just me missing something, but... You are actually not writing the contents of the file to stdout. You are just reading it into memory, so it will never show up on the other side of the TCP connection...

Try:

sys.stdout.write(open(filepath,"rb").read())
sys.stdout.flush()

Depending on the file size, it might be better to read the file in chunks, like so:

chunk_size = 4096
handle = open(filepath, "rb")

while True:
    buffer = handle.read(chunk_size)
    if buffer:
        sys.stdout.write(buffer)
    else:
        break

Another thing to be aware of: writing binary data to stdout may cause Python to choke due to encoding issues. This depends on the Python version you are using.

Dirk
wow, I've never posted on this forum before. You guys are incredible!!
Scott
Scott, if an answer solves your problem, remember to accept it (use the checkmark icon below the number giving upvotes for the answer): that's fundamental SO behavior!
Alex Martelli
A: 

You should check out urllib to set and work with headers. Here's a small example that does this.

Ólafur Waage
I've never understood how to use this module in an ajax situation. As in the example, all the headers and url come together into a request, but I'm responding, not making a request. How does that work?
Scott
The urllib and urllib2 libraries are indeed for opeing ulr's (making http requests) and not for responding to them - so this answer does not help.
James Fassett
+1  A: 

I don't know if this is the only issue but the python print statement terminates lines with "\n" whereas HTTP headers need to be terminated with "\r\n"

Greg