0

I have this smartReadFile() php function that allows to play an audio stream from a file. How would you modify this function so it queries mysql database BLOB instead of reading a specific file?

function smartReadFile($location, $filename, $mimeType = 'audio/octet-stream')
{
if (!file_exists($location))
{
    header ("HTTP/1.1 404 Not Found");
    return;
}

$size   = filesize($location);
$time   = date('r', filemtime($location));

$fm     = @fopen($location, 'rb');
if (!$fm)
{
    header ("HTTP/1.1 505 Internal server error");
    return;
}

$begin  = 0;
$end    = $size - 1;

if (isset($_SERVER['HTTP_RANGE']))
{
    if (preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches))
    {
        $begin  = intval($matches[1]);
        if (!empty($matches[2]))
        {
            $end    = intval($matches[2]);
        }
    }
}

if (isset($_SERVER['HTTP_RANGE']))
{
    header('HTTP/1.1 206 Partial Content');
}
else
{
    header('HTTP/1.1 200 OK');
}

header("Content-Type: $mimeType"); 
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: no-cache');  
header('Accept-Ranges: bytes');
header('Content-Length:' . (($end - $begin) + 1));
if (isset($_SERVER['HTTP_RANGE']))
{
    header("Content-Range: bytes $begin-$end/$size");
}
header("Content-Disposition: inline; filename=$filename");
header("Content-Transfer-Encoding: binary");
header("Last-Modified: $time");

$cur    = $begin;
fseek($fm, $begin, 0);

while(!feof($fm) && $cur <= $end && (connection_status() == 0))
{
    print fread($fm, min(1024 * 16, ($end - $cur) + 1));
    $cur += 1024 * 16;
}
}
Chris
  • 5,516
  • 1
  • 26
  • 30
Marcin S.
  • 11,161
  • 6
  • 50
  • 63
  • 1
    Instead of fopen, do query/fetch? – Explosion Pills Oct 03 '12 at 15:43
  • In my opinion, you should fetch file from db to temporary file and stream this file. It can take cache functionality also. But continuous reading from database, I really do not know. I do not think it is good idea, specially, if more than one user can be streaming one file... – Fanda Oct 03 '12 at 15:46
  • Thank you for the suggestions. I'm not very familiar with php but I'll definitely give it a shot. So I would have: $result = @mysqli_query($dbc, $query); $row = mysqli_fetch_array($result); $fm = $row['file']; How about this line that contains $filename? header("Content-Disposition: inline; filename=$filename"); – Marcin S. Oct 03 '12 at 15:49
  • @Fanda. Thanks for the reply. I tried to avoid saving anything to the server. However I would need to redisign my application if I won't be able to read directly from db – Marcin S. Oct 03 '12 at 15:53
  • 1
    I don't know if it is possible to read just part of blob. I also don't know, why you have files in database. My way would be to create directory as file cache, and read file from database only if file doesn't exists in the cache. Then you do not need refactoring, but extending you program by db reading functionality. – Fanda Oct 03 '12 at 15:58
  • Like Fanda said, it is a bad idea to use a db for this. A blob could be converted to a byte array and then streamed, but you will likely need to download the whole thing first. – Anton Soradoi Oct 03 '12 at 16:03
  • @Fanda Actually my mobile app is sending the files into db directly and know I want to play them back in a device. I got it working as you said when I read a blob, save it into the file and then stream it. I was thinking if I can avoid saving the files into a server. – Marcin S. Oct 03 '12 at 16:31
  • @Anton. Is it more expensive operation to convert a blob into byte array, download it and then stream from it in the client side than just save a blob into a file in the server and play a stream from it? – Marcin S. Oct 03 '12 at 16:32
  • @MarcinS. The only way to know for sure is to do some profiling and compare the results. However, if you are able to stream the file directly from the server it should be faster than downloading the whole thing as a blob and then streaming it. (The conversion of a blob to byte array should be trivial in comparison to a db query.) – Anton Soradoi Oct 03 '12 at 17:23
  • These comments are ridiculous. All you have to do is fetch the data, like any other query result, and output it. No, the data won't be streamed in from the database unless you were to write your own DB client. However, that won't matter much. Your files won't be that big. – Brad Oct 03 '12 at 20:46
  • As Explosion Pills suggested I'm using query/fetch instead of fopen however I have hard time with it. Could you modify this code and post your answer? – Marcin S. Oct 03 '12 at 22:24

0 Answers0