Solved

force download for mp3 files

Posted on 2006-07-03
10
349 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

I imagine that there are some, like me, who require a way of getting currency exchange rates for implementation in web project from time to time, so I thought I would share a solution that I have developed for this purpose. It turns out that Yaho…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

739 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