0

When using computer files are downloaded normally. Problem start on android browsers.

When we download a file from android default browser, the file is downloaded but it is of 0.00 bytes, so not technically present there(corrupt file).

When we download file from any third party application like or opera it gives error that "file could not be downloaded." not the header error. And files could be downloaded via UC Browser and Chrome and Firefox. But still gives the error in default browser.

Here is the code I am using:

<?php
require 'php/db.php';
if(isset($_POST['file_id'])&&!empty($_POST['file_id'])){
    download_file($_POST['file_id']);
}
function download_file($id){
    global $con;
    $id = mysqli_real_escape_string($con,htmlentities($id));
    $file="SELECT file_name,file_title,file_size,down FROM files WHERE file_id= $id";
    $result = mysqli_query($con,$file);
    $row = mysqli_fetch_assoc($result);
    $name = $row['file_name'];
    $title = $row['file_title'];
    $size = $row['file_size'];
    $ext = strtoupper(ext($name));  // Function defined bellow
    $down = $row['down'];
    $newname = $title.'.'.$ext;
    $olddir = "files/".$name;
    $down++;

    if(is_file($olddir)) {
        $update_down = "UPDATE files SET down = $down WHERE file_id = '$id'";
        $update_down_result = mysqli_query($con,$update_down);

        header('Pragma: public');   // required
        header('Expires: 0');       // no cache
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($olddir)).' GMT');
        header('Cache-Control: private',false);
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="'.$newname.'"');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: '.$size);   // provide file size
        header('Connection: close');
        readfile($olddir);

        exit();
    }else header("Location: index.php?msg=Sorry!+File+could+not+be+downloaded");

}

function ext($name){
    $rut = strrev($name);
    $erut = explode('.', $rut);
    return strrev($erut[0]);
}

We give file id to this function and it downloads the file on PC.

Can anyone tell me how to remove the error? So that users can download files from their android phones too.

Paras
  • 685
  • 6
  • 16
  • http://stackoverflow.com/questions/4674737/avoiding-content-type-issues-when-downloading-a-file-via-browser-on-android check out this question, it suggests putting the extension in capitals. – STLMikey Apr 22 '15 at 16:37
  • write the Content-Disposition filename extension in UPPERCASE for this i change the line $ext = strtoupper(ext($name)); and now if we download the extension comes in upper case but still not able to download in mobile. If you want to try please download a file from www.skyshare.in – Paras Apr 22 '15 at 16:50
  • Please post a download link here. – greenapps Apr 22 '15 at 20:28
  • `r or opera it gives error that file could not be downloaded.`. Do you mean that they display this message: `else header("Location: index.php?msg=Sorry!+File+could+not+bue+downloaded");` ? – greenapps Apr 22 '15 at 20:34
  • `We give file id to this function`. Please show how you do that. You forgot to tell that your script name is `downfile.php` and that the browser should POST `file_id` value to your script when one of the Download buttons is clicked. – greenapps Apr 22 '15 at 20:53
  • Chrome on Android does all ok. Didn't you test Chrome? – greenapps Apr 22 '15 at 21:03

2 Answers2

0

Probably $size == 0;

$size = $row['file_size'];
...
$olddir = "files/".$name;

change to

$olddir = "files/".$name;
$size = filesize($olddir);

And change

else header("Location: index.php?msg=Sorry!+File+could+not+be+downloaded");

to

else header("Location: index.php?msg=Sorry!+File+could+not+be+found+on+server: " . $olddir);
greenapps
  • 11,154
  • 2
  • 16
  • 19
  • Still not working. I changed my code as you suggested. but no. There is same problem. – Paras Apr 24 '15 at 13:57
  • Your code with the changes i suggested runs perfectly at my server. But i use a GET request. You could try that too as a test. – greenapps Apr 24 '15 at 13:59
  • You can prepare your script for both POST and GET by just adding `if(isset($_GET['file_id'])&&!empty($_GET['file_id'])){ download_file($_GET['file_id']);` – greenapps Apr 24 '15 at 14:00
  • If you do that you could post a get link here too so everybody could test and see it. Like http://www.skyshare.in/downfile.php?file_id=75 – greenapps Apr 24 '15 at 14:09
0

I got the solution. Mainly I changed two things:

  1. Used GET method instead of Post Method.
  2. Used Flush and ob_clean functions to clear the buffer.

New code for downfile.php is like this:

<?php
    require '../php/db.php';
    ob_start();
    if(isset($_GET['file_id'])&&!empty($_GET['file_id'])){
        download_file($_GET['file_id']);
    }else die("There was an error in downloading file. Please try again later.");

    function download_file($id){
        global $con;
        $id = mysqli_real_escape_string($con,htmlentities($id));

        $file="SELECT file_name,file_title,file_size,down FROM files WHERE file_id= $id";
        $result = mysqli_query($con,$file);
        $row = mysqli_fetch_assoc($result);
        $name = $row['file_name'];
        $title = $row['file_title'];
        $ext = ext($name);
        $down = $row['down'];
        $newname = $title.'.'.$ext;
        $size = $row['file_size'];
        $down++;

        if(is_file($name)) {
            $update_down = "UPDATE files SET down = $down WHERE file_id = '$id'";
            $update_down_result = mysqli_query($con,$update_down);

            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="'.$newname.'"');
            header('Content-Transfer-Encoding: binary');
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: '.$size);
            ob_clean();
            flush();
            readfile($name);
            exit;

        }else header("Location: index.php?msg=Sorry!+File+could+not+found!");

    }

    function ext($name){
        $rut = strrev($name);
        $erut = explode('.', $rut);
        return strrev($erut[0]);
    }

?>

Through this code I am able to download files in android browsers too.

Hope this may help. :)

Paras
  • 685
  • 6
  • 16