2011-01-16 35 views
7

Tôi đang cố gắng buộc tải xuống tệp từ máy chủ web của mình bằng cách sử dụng PHP. Tôi không phải là chuyên gia về PHP nhưng tôi dường như không thể giải quyết vấn đề về các tệp tải xuống có kích thước 0 byte.Tải xuống PHP Force Gây ra 0 tệp byte

Mã sản phẩm:

$filename = "FILENAME..."; 

header("Content-type: $type"); 
header("Content-Disposition: attachment;filename=$filename"); 
header("Content-Transfer-Encoding: binary"); 
header('Pragma: no-cache'); 
header('Expires: 0'); 
set_time_limit(0); 
readfile($file); 

Ai có thể giúp đỡ? Cảm ơn.

+2

Bạn có chắc chắn các tập tin được tồn tại bằng con đường đó và có một số nội dung? – Gumbo

+1

Chỉ là một lưu ý nhỏ, nhưng bạn nên chú ý đến việc truyền tải thư mục. Một kẻ tấn công tiềm năng có thể sử dụng, ví dụ, "../../../../var/www/config.php" và có thể đọc một số dữ liệu nhạy cảm. –

+0

bất kỳ giải pháp cho vấn đề này, phải đối mặt với cùng một vấn đề –

Trả lời

2

tôi sử dụng phương pháp sau đây trong phunction và tôi đã không có bất kỳ vấn đề với nó cho đến nay:

function Download($path, $speed = null) 
{ 
    if (is_file($path) === true) 
    { 
     $file = @fopen($path, 'rb'); 
     $speed = (isset($speed) === true) ? round($speed * 1024) : 524288; 

     if (is_resource($file) === true) 
     { 
      set_time_limit(0); 
      ignore_user_abort(false); 

      while (ob_get_level() > 0) 
      { 
       ob_end_clean(); 
      } 

      header('Expires: 0'); 
      header('Pragma: public'); 
      header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
      header('Content-Type: application/octet-stream'); 
      header('Content-Length: ' . sprintf('%u', filesize($path))); 
      header('Content-Disposition: attachment; filename="' . basename($path) . '"'); 
      header('Content-Transfer-Encoding: binary'); 

      while (feof($file) !== true) 
      { 
       echo fread($file, $speed); 

       while (ob_get_level() > 0) 
       { 
        ob_end_flush(); 
       } 

       flush(); 
       sleep(1); 
      } 

      fclose($file); 
     } 

     exit(); 
    } 

    return false; 
} 

Bạn có thể thử nó chỉ đơn giản bằng cách thực hiện:

Download('/path/to/file.ext'); 
+0

Đẹp chút thực hiện để điều chỉnh :) – RobertPitt

+1

Cảm ơn bạn rất nhiều, nhưng nó không có vẻ làm việc:/ – Alex

+0

Ai sẽ bỏ phiếu này? – RobertPitt

6

Bạn không kiểm tra xem tệp có tồn tại không. Hãy thử sử dụng tính năng này:

$file = 'monkey.gif'; 

if (file_exists($file)) 
{ 
    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename='.basename($file)); 
    header('Content-Transfer-Encoding: binary'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Pragma: public'); 
    header('Content-Length: ' . filesize($file)); 
    ob_clean(); 
    flush(); 
    readfile($file); 
    exit; 
}else 
{ 
    echo "File does not exists"; 
} 

Và xem những gì bạn nhận được.


Bạn cũng nên lưu ý rằng điều này buộc tải xuống dưới dạng luồng octet, một tệp nhị phân thuần túy. Một số trình duyệt sẽ đấu tranh để hiểu chính xác loại tệp. Ví dụ: nếu bạn gửi GIF có tiêu đề là Content-Type: application/octet-stream thì trình duyệt có thể không xử lý ảnh GIF như hình ảnh GIF. Bạn nên thêm các kiểm tra cụ thể để xác định loại nội dung của tệp và gửi tiêu đề Content-Type thích hợp.

+0

Cảm ơn Robert, nhưng dường như không hoạt động:/ – Alex

+1

Tính năng này hoạt động, tôi nghĩ bạn cần mở rộng câu hỏi của mình với trình duyệt bạn đang sử dụng, tệp, vị trí của nó, quyền của tệp cũng như thư mục, và máy chủ của bạn đang chạy. – RobertPitt

+0

cảm ơn vì điều này. Tôi đã có vấn đề 0 byte với các tập tin ppt chỉ. Ob_clean() và flush() trước khi stream_get_contents() giúp đỡ. – pduersteler

2

Bạn cần phải xác định Content-Length tiêu đề:

header("Content-Length: " . filesize($filename)); 

Ngoài ra, bạn không nên gửi một tiêu đề Content-Transfer-Encoding. Cả hai số HTTP/1.0HTTP/1.1 specs state là "HTTP không sử dụng trường Mã hóa chuyển giao nội dung (CTE) của RFC 1521".

1

Vấn đề này giống với dự án trang web của tôi. Mã này tôi đã sử dụng:

<?php 

$file = $_SERVER["DOCUMENT_ROOT"].'/.../.../'.$_GET['file']; 

if(!file) 
{ 
    // File doesn't exist, output error 
    die('file not found'); 
} 
else 
{ 

    //$file_extension = strtolower(substr(strrchr($file,"."),1)); 
    $file_extension = end(explode(".", $file)); 

    switch($fileExtension) 
    { 
    case "pdf": $ctype="application/pdf"; break; 
    case "exe": $ctype="application/octet-stream"; break; 
    case "zip": $ctype="application/zip"; break; 
    case "doc": $ctype="application/msword"; break; 
    case "xls": $ctype="application/vnd.ms-excel"; break; 
    case "ppt": $ctype="application/vnd.ms-powerpoint"; break; 
    case "gif": $ctype="image/gif"; break; 
    case "png": $ctype="image/png"; break; 
    case "jpeg": 
    case "jpg": $ctype="image/jpg"; break; 
    default: $ctype="application/force-download"; 
    } 

    nocache_headers(); 

    // Set headers 
    header("Pragma: public"); // required 
    header("Expires: 0"); 
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
    header("Cache-Control: public"); // required for certain browsers 
    header("Content-Description: File Transfer"); 
    header("Content-Type: $ctype"); 
    header("Content-Disposition: attachment; filename=".$file.";"); 
    header("Content-Transfer-Encoding: binary"); 
    header("Content-Length: ".filesize($file)); 

    readfile($file); 
} 
?> 

Tôi nghĩ vấn đề nằm ở cài đặt máy chủ như cài đặt PHP hoặc cài đặt bộ nhớ cache, nhưng tôi không có ý tưởng nào để thực hiện ý kiến ​​này.

1

tôi đang làm điều này để tải về một tập tin PDF ...

$filename = 'Application.pdf'; 
header("Content-Type: application/pdf"); 
header("Content-Disposition: attachment; filename=$filename"); 
echo $pdf; 

tôi nghĩ rằng bạn đang thiếu hàng cuối cùng, nơi mà bạn thực sự gửi các nội dung tập tin của bất cứ điều gì bạn có trong $file.

Pablo

0

Tệp đã mở cho tôi khi tôi thay đổi thư mục thành vị trí tệp.

$reportLocation = REPORTSLOCATION; 

$curDir = getcwd(); 

chdir($reportLocation); 

if (file_exists($filename)) { 

    header('Content-Disposition: attachment; filename="' . $filename . '"'); 
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); 
    header('Content-Length: ' . filesize($filename)); 
    header('Content-Transfer-Encoding: binary'); 
    header('Cache-Control: must-revalidate'); 
    header('Pragma: public'); 

    ob_clean(); 
    flush(); 

    readfile($filename); 
} 
chdir($curDir); 
0

Bí quyết là kiểm tra với tệp_exists để xác nhận đường dẫn chính xác. Sự nhầm lẫn lớn là đối với các đường dẫn PHP bạn không cần phải bắt đầu bằng '/' để nói đường dẫn bắt đầu trang web của bạn.

'/folder/file.ext' #bad, needs to know the real full path 

trong php/là đường dẫn chính của trang web, bạn không cần phải đề cập đến nó. Chỉ cần:

'folder/file.ext' #relative to the/website 

này sẽ làm việc với file_exists, tiêu đề filename, readfile, vv ...

Các vấn đề liên quan