2009-11-22 35 views
11

Tôi đang viết kịch bản tải xuống chống đọc sách và kế hoạch của tôi là tạo tệp tạm thời, được đặt tên theo ID phiên, sau khi phiên hết hạn, tệp sẽ tự động bị xóa. Có thể không? Và bạn có thể cho tôi một số lời khuyên làm thế nào để làm điều đó trong PHP?Tạo tập tin tạm thời và tự động xóa

Cảm ơn rất nhiều cho bất kỳ trả lời

+0

Tệp sẽ được giữ trong bao lâu? – Ikke

+0

Bạn có thể vui lòng cụ thể hơn về những gì bạn đang cố gắng đạt được không? Anti-Leeching DL Script là một chút mơ hồ. UseCase hoặc vấn đề mà kịch bản đang cố gắng giải quyết là gì? – Gordon

+0

Xin chào lkke, Tôi chỉ muốn cho phép người dùng tải xuống trong phiên của anh ấy/cô ấy, chẳng hạn như anh ấy không thể sao chép và dán liên kết cho người khác Hi Gordon, Tôi muốn buộc người dùng tải xuống tệp từ trang web của tôi, kiểm soát tốc độ. Vì vậy, tôi nghĩ rằng để tạo một tập tin tạm thời trong một thư mục tạm thời trong tài liệu HTTP để người dùng có thể tải xuống và sau đó gỡ bỏ chúng (tự động) sau khi hết hạn – mrblue

Trả lời

9

Vì vậy, chúng tôi có một hoặc nhiều tệp có sẵn để tải xuống. Tạo một tệp tạm thời cho mỗi yêu cầu tải xuống không phải là một ý tưởng hay. Thay vào đó, việc tạo một symlink() cho mỗi tệp là một ý tưởng tốt hơn nhiều. Điều này sẽ tiết kiệm được không gian đĩa và giảm tải máy chủ.

Đặt tên cho liên kết tượng trưng sau phiên của người dùng là ý tưởng tốt. Ý tưởng tốt hơn là tạo một tên liên kết ngẫu nhiên & liên kết với phiên, do đó, tập lệnh có thể xử lý nhiều lượt tải xuống mỗi phiên. Bạn có thể sử dụng session_set_save_handler() (link) và đăng ký chức năng tùy chỉnh read để kiểm tra các phiên đã hết hạn và xóa các liên kết tượng trưng khi phiên hết hạn.

+1

Hi pygorex1, Đây chính xác là những gì tôi đang tìm kiếm. Cám ơn rất nhiều. – mrblue

+0

Chỉ có vấn đề là, symlink không hoạt động trên php ver 5.2 – coderama

+0

Liên kết bây giờ là 404, chỉ cần ping bạn để bạn có thể sửa nó –

8

PHP có một chức năng cho tên đó tmpfile. Nó tạo ra một tệp tạm thời và trả về một tài nguyên. Tài nguyên có thể được sử dụng như bất kỳ tài nguyên nào khác.

Ví dụ: ví dụ từ hướng dẫn sử dụng:

<?php 
$temp = tmpfile(); 
fwrite($temp, "writing to tempfile"); 
fseek($temp, 0); 
echo fread($temp, 1024); 
fclose($temp); // this removes the file 
?> 

Tệp sẽ tự động bị xóa khi đóng (sử dụng fclose()) hoặc khi tập lệnh kết thúc. Bạn có thể sử dụng bất kỳ chức năng tệp nào trên tài nguyên. Bạn có thể tìm thấy các số here này. Hy vọng điều này sẽ giúp bạn?

Một giải pháp khác là tạo tệp theo cách thông thường và sử dụng cronjob để kiểm tra thường xuyên nếu phiên hết hạn. Ngày hết hạn và dữ liệu phiên khác có thể được lưu trữ trong cơ sở dữ liệu. Sử dụng tập lệnh để truy vấn dữ liệu đó và xác định xem phiên có hết hạn hay không. Nếu vậy, hãy gỡ bỏ nó ra khỏi đĩa. Đảm bảo chạy tập lệnh mỗi giờ một lần (tùy thuộc vào thời gian chờ của bạn).

+0

Tôi không nghĩ đó là giải pháp cho câu hỏi của mrblue khiến tệp bị xóa vào tập lệnh cuối/fclose() chứ không phải khi phiên hết hạn. –

+0

Bạn nói đúng. Phải đọc qua phần đó. Đã thêm thông tin vào bài đăng của tôi. Bây giờ là tùy thuộc vào anh ấy;) – TheGrandWazoo

+0

Xin chào TheGrandWazoo, cảm ơn câu trả lời của bạn. Tôi đã nghĩ về giải pháp đó, nhưng không thể thực hiện được vấn đề hiệu suất nếu trang web tăng lên và Philippe đúng, mối quan tâm của tôi là PHP hỗ trợ chức năng "móc", như được gọi tự động sau khi phiên hết hạn hoặc bắt đầu. – mrblue

2

Tôi khuyên bạn không nên sao chép tệp ở địa điểm đầu tiên. Tôi sẽ làm như sau: khi người dùng yêu cầu tệp, bạn tạo một chuỗi duy nhất ngẫu nhiên để cho anh ta liên kết theo cách này: dl.php?k=hd8DcjCjdCkk123 sau đó đặt chuỗi này vào cơ sở dữ liệu, lưu trữ địa chỉ IP của anh ấy, có thể phiên và thời gian bạn đã tạo liên kết. Sau đó, một người dùng khác yêu cầu tệp đó, đảm bảo tất cả các nội dung (băm, ip, v.v ..) và liên kết không hết hạn (ví dụ: không phải là N giờ đã trôi qua kể từ khi tạo) và nếu mọi thứ đều ổn, hãy sử dụng PHP cho đường ống tập tin. Đặt công việc cron để xem qua DB và xóa các mục đã hết hạn. Bạn nghĩ sao?

tmpfile

Tạo một tập tin tạm thời với một tên duy nhất trong read-write (w +) Chế độ và trả về một tập tin xử lý. Tệp được tự động xóa khi đóng (sử dụng fclose()) hoặc khi tập lệnh kết thúc.

+0

Tôi không nghĩ đó là giải pháp cho câu hỏi của mrblue khiến tệp bị xóa vào tập lệnh cuối/fclose() chứ không phải khi phiên hết hạn. –

+0

Hi roddik, Philippe đã đúng, tôi nghĩ về giải pháp đó, nhưng nó không được áp dụng trong trường hợp của tôi đặc biệt là vấn đề hiệu suất – mrblue

3

Bạn có thể giải thích vấn đề của mình sâu hơn một chút không? Bởi vì tôi không thấy lý do tại sao không sử dụng $_SESSION. Dữ liệu trong $_SESSION được lưu trữ phía máy chủ trong một tệp (xem http://php.net/session.save-path) BTW. Ít nhất theo mặc định. ;-)

+0

Hi Philippe, Vâng, tôi thực sự muốn sử dụng $ _SESSION (thực sự tôi đã làm), nhưng Tôi không thể tìm thấy bất kỳ tài liệu hoặc chủ đề nào để đề cập đến điều gì đó, chẳng hạn như hành động "móc", ví dụ: chúng tôi có thể thực hiện một chức năng mà hệ thống tự động gọi sau khi phiên hết hạn hoặc bắt đầu. Đó là ý tưởng và mối quan tâm của tôi. Cảm ơn thời gian của bạn – mrblue

+0

đi theo cách khác. phản ứng khi một phiên mới được tạo (ví dụ: $ _SESSION trống và bạn đã điền nó trước đó), không phải khi một phiên hết hạn. vấn đề là, một phiên có thể hết hạn mà không có bất kỳ hành động nào được thực hiện bởi người dùng (phiên bị lỗi thời và bị bộ thu gom rác loại bỏ). Bạn đang cố gắng để làm chính xác? –

2

Ok, vì vậy chúng tôi có các yêu cầu sau cho đến nay

  1. Hãy để tải về người dùng trong/phiên của mình chỉ
  2. không sao chép & dán liên kết cho người khác
  3. Người dùng có để tải xuống từ trang web, ví dụ: không có hotlinking
  4. Tốc độ điều khiển

Hãy xem.Đây là không mã làm việc, nhưng nó phải làm việc cùng những dòng này:

<?php // download.php 

session_start(); // start or resume a session 

// always sanitize user input 
$fileId = filter_input(INPUT_GET, 'fileId', FILTER_SANITIZE_NUMBER_INT); 
$token = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW); 
$referer = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL); 
$script = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL); 

// mush session_id and fileId into an access token 
$secret  = 'i can haz salt?'; 
$expectedToken = md5($secret . session_id() . $fileId); 

// check if request came from download.php and has the valid access token 
if(($expectedToken === $token) && ($referer === $script)) { 
    $file = realpath('path/to/files/' . $fileId . '.zip'); 
    if(is_readable($file)) { 
     session_destroy(); // optional 
     header(/* stuff */); 
     fpassthru($file); 
     exit; 
    } 
} 
// if no file was sent, send the page with the download link. 
?> 
<html ... 

<?php printf('a href="/download.php?fileId=%s&amp;token=%s', 
       $fileId, $expectedToken); ?> 

... 
</html> 

Và đó là nó. Không yêu cầu cơ sở dữ liệu. Điều này cần bao gồm các yêu cầu 1-3. Bạn không thể kiểm soát tốc độ với PHP, nhưng nếu bạn không hủy phiên sau khi gửi một tệp, bạn có thể ghi một phiên truy cập vào phiên và giới hạn số lượng tệp mà người dùng sẽ được gửi trong phiên.

Tôi hết lòng đồng ý rằng điều này có thể được giải quyết một cách thanh lịch hơn nhiều so với bản hack dạng khỉ này, nhưng như là bằng chứng-khái niệm, nó phải là đủ.

+0

Hi Gordon, Đó là gần 90% những gì tôi đã viết trong mã của tôi, nhưng bạn có một kiểm tra bảo mật tốt hơn với mã thông báo. Nhiều đánh giá cao cho điều đó. – mrblue

+0

Mã thông báo thêm bảo mật, nhưng nó cũng khiến bạn không phải liên kết hoặc sao chép tệp của mình nữa, vì mã thông báo là duy nhất cho tệp phiên +. Mã thông báo về cơ bản những gì pygorex1 sẽ tạo ra cho một tên liên kết tượng trưng. Thay vì tạo một liên kết tượng trưng từ nó mà sau này bạn sẽ phải loại bỏ bằng cách nào đó, bạn chỉ cần gửi tên/mã thông báo với fileId thông thường. Ít bảo trì hơn. – Gordon

0

Có thể đã đến muộn để trả lời nhưng tôi cố gắng chia sẻ về tính năng googlize!

nếu bạn sử dụng CPanel có một cách ngắn gọn và nhanh chóng để chặn bên ngoài yêu cầu trên các tập tin lưu trữ của bạn có tên là: HotLink.

bạn có thể bật HotLinks trên Cpanel và đảm bảo không ai có thể yêu cầu tệp của bạn từ một máy chủ lưu trữ khác hoặc sử dụng tệp của bạn làm tài liệu tham khảo tải xuống.

0

Để đạt được điều này, tôi sẽ tạo một tệp và bảo vệ tệp bằng cách sử dụng chmod - làm cho nó không khả dụng cho công chúng. Hoặc, cách khác, lưu nội dung trong hàng của bảng cơ sở dữ liệu, tìm nạp nó bất cứ khi nào được yêu cầu.

Làm cho tệp có thể tải xuống dưới dạng tệp. Để làm như vậy, tôi sẽ lấy nội dung từ tệp được bảo vệ, hoặc nếu nó được lưu trữ trong một bảng cơ sở dữ liệu, hãy lấy nó và chỉ cần xuất nó ra. Sử dụng tiêu đề php, tôi sẽ cung cấp cho nó một tên mong muốn, phần mở rộng, chỉ định kiểu của nó, và cuối cùng buộc trình duyệt tải xuống đầu ra dưới dạng tệp rắn.

Bằng cách này, bạn chỉ cần lưu dữ liệu ở một nơi, trong tệp được bảo vệ hoặc trong cơ sở dữ liệu. Buộc trình duyệt của khách hàng tải xuống trình duyệt nhiều lần khi các điều kiện đáp ứng, ví dụ như người dùng đã đăng nhập và cứ tiếp tục như vậy. Không cần phải lo lắng về không gian đĩa, tạo bất kỳ tệp tạm thời nào, cronJob và tự động xóa tệp.

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