Solved

force download for mp3 files

Posted on 2006-07-03
10
342 Views
Last Modified: 2008-02-01
I have downloadedable files on my server for clients to download, however I dont want them played in the browser, I want the download prompt to happen

what do I have to do...  as of right now all I have is the actual link to the mp3 file
0
Comment
Question by:prowebinteractive
  • 2
  • 2
  • 2
  • +2
10 Comments
 
LVL 49

Expert Comment

by:Roonaan
ID: 17034864
You have to write a download.php file which is called like downloadmp3.php?filemysoundfile.mp3

then have it like this:
<?php

  $mp3dir = 'mp3/';
 
  if(empty($_GET['file'])) exit('File not found');
 
  $file = basename($_GET['file']);
 
  if(!is_file($mp3dir.$file)) exit('File not found');
 
  header('Content-type:attachment;filename='.$file);
  readfile($mpd3dir.$file);
?>

-r-
0
 

Author Comment

by:prowebinteractive
ID: 17034955
doesnt appear to work

I get this error:

mp3Complete/BlackcacoDaleconlacinturacomplete.mp3
Warning: Cannot modify header information - headers already sent by (output started at /home/bcadmin/public_html/newsite/myOrder.php:14) in /home/bcadmin/public_html/newsite/myOrder.php on line 19
0
 
LVL 1

Accepted Solution

by:
duckax earned 250 total points
ID: 17034973
If you want to support download resuming as well as send the filesize to the user, you will need a few more lines of code.

I got this code off php.net with a little modification so that it supports IE
You pass the file using GET i.e. script.php?file=song.mp3
Modify $fpath to the directory where your mp3 is stored

<?php
$fname = $_GET['file'];
$fpath = "downloads/$fname";
$fsize = filesize($fpath);
$bufsize = 20000;

if(isset($_SERVER['HTTP_RANGE']))  //Partial download
{
   if(preg_match("/^bytes=(\\d+)-(\\d*)$/", $_SERVER['HTTP_RANGE'], $matches)) { //parsing Range header
       $from = $matches[1];
       $to = $matches[2];
       if(empty($to))
       {
           $to = $fsize - 1;  // -1  because end byte is included
                               //(From HTTP protocol:
// 'The last-byte-pos value gives the byte-offset of the last byte in the range; that is, the byte positions specified are inclusive')
       }
       $content_size = $to - $from + 1;

       header("HTTP/1.1 206 Partial Content");
       header('Cache-Control: public');
       header("Content-Range: $from-$to/$fsize");
       header("Content-Length: $content_size");
       header("Content-Type: application/force-download");
       header("Content-Disposition: attachment; filename=$fname");
       header("Content-Transfer-Encoding: binary");

       if(file_exists($fpath) && $fh = fopen($fpath, "rb"))
       {
           fseek($fh, $from);
           $cur_pos = ftell($fh);
           while($cur_pos !== FALSE && ftell($fh) + $bufsize < $to+1)
           {
               $buffer = fread($fh, $bufsize);
               print $buffer;
               $cur_pos = ftell($fh);
           }

           $buffer = fread($fh, $to+1 - $cur_pos);
           print $buffer;

           fclose($fh);
       }
       else
       {
           header("HTTP/1.1 404 Not Found");
           exit;
       }
   }
   else
   {
       header("HTTP/1.1 500 Internal Server Error");
       exit;
   }
}
else // Usual download
{
   header("HTTP/1.1 200 OK");
   header('Cache-Control: public');
   header("Content-Length: $fsize");
   header("Content-Type: application/force-download");
   header("Content-Disposition: attachment; filename=$fname");
   header("Content-Transfer-Encoding: binary");

   if(file_exists($fpath) && $fh = fopen($fpath, "rb")){
       while($buf = fread($fh, $bufsize))
           print $buf;
       fclose($fh);
   }
   else
   {
       header("HTTP/1.1 404 Not Found");
   }
}
?>
0
 
LVL 1

Expert Comment

by:duckax
ID: 17034989
You cannot include any other output at the beginning of the script. Remove any non-php, blank lines, print and echo statements
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 1

Expert Comment

by:dimakh
ID: 17036748
Hi prowebinteractive,

I'm posting in reference with both of the above posts.
both solution may work with your problem.
please add following code at the start of page. so you wont get any warning messages saying "headers already sent by..." no matter if you are adding any other codes before sending out headers.


<?php
ob_start();
?>

Add above code at very start of your script (at 1st line itself) and your problem will be resolved.

please check this and let me know if you still any error message on this.

Thanks.
0
 
LVL 49

Expert Comment

by:Roonaan
ID: 17036765
>doesnt appear to work

>I get this error:

>mp3Complete/BlackcacoDaleconlacinturacomplete.mp3
>Warning: Cannot modify header information - headers already sent by (output started at /home/bcadmin/public_html/newsite/myOrder.php:14) in >/home/bcadmin/public_html/newsite/myOrder.php on line 19

As mentioned. You should call the file on its own. Not embed it into html.

-r-
0
 
LVL 1

Expert Comment

by:dimakh
ID: 17070791
Hi,

here is the complete code for forced download:
<?
      $url_path      = $music_full_song.$file_name;     // absolute path for the mp3 file
      
      header("Pragma: public"); // required
      header("Expires: 0");
      header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
      header("Cache-Control: private",false); // required for certain browsers
      header("Content-Type: application/force-download");
      // change, added quotes to allow spaces in filenames
      header("Content-Disposition: attachment; filename=\"".basename($file_name)."\";" );
      header("Content-Transfer-Encoding: binary");
      header("Content-Length: ".filesize($url_path));
      readfile("$url_path");
      exit();
?>

you should open this file in a new page/window .

Thanks.
0
 
LVL 2

Assisted Solution

by:Linky
Linky earned 250 total points
ID: 17108268
If you are going to use a script to force download MP3, make sure you do:

$filename = str_replace('/', '', $filename);
$filename = str_replace('..', '', $filename);

Before processing it. Because someone can easily type stuff like song.php?file=../../somefile.ext and possibly get files that contain password information or server info that you do not want them getting.

Just as a security measure.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Deprecated and Headed for the Dustbin By now, you have probably heard that some PHP features, while convenient, can also cause PHP security problems.  This article discusses one of those, called register_globals.  It is a thing you do not want.  …
Things That Drive Us Nuts Have you noticed the use of the reCaptcha feature at EE and other web sites?  It wants you to read and retype something that looks like this.Insanity!  It's not EE's fault - that's just the way reCaptcha works.  But it is …
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

26 Experts available now in Live!

Get 1:1 Help Now