Solved

force download for mp3 files

Posted on 2006-07-03
10
344 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
ScreenConnect 6.0 Free Trial

Discover new time-saving features in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

 
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

NAS Cloud Backup Strategies

This article explains backup scenarios when using network storage. We review the so-called “3-2-1 strategy” and summarize the methods you can use to send NAS data to the cloud

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Move wordpress site 3 38
Is there a limit to how many inner joins you should use? 4 31
Dynamic varibles 5 32
google analytics on wp-admin password protected area 2 23
Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
This article discusses how to create an extensible mechanism for linked drop downs.
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…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

773 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