2010-06-09 15 views
6

मेरे पास एक php फ़ाइल है जो उन सभी फ़ाइलों के लिए द्वारपाल के रूप में कार्य करती है जिन्हें मैं लोगों को डाउनलोड करना चाहता हूं, जो पर्याप्त निजीकरण प्राप्त करते हैं।उपयोगकर्ताओं को आवश्यक अनुमति के साथ कैसे php के माध्यम से फ़ाइल डाउनलोड करने दें?

कोड मैं उपयोगकर्ता के लिए फ़ाइल फेंक का उपयोग

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header("Content-disposition: attachment; filename=\"".$public_filename."\""); 
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: ".$f_filesize); 
readfile($file_path); 

अधिकांश फ़ाइलें काफी बड़ी .... 400MB-10GB कर रहे हैं।

ऐसा करने का एक अच्छा तरीका क्या होगा, और सही स्थान + फ़ाइल नाम गुप्त रखें, इसलिए लोग सीधे फाइलों से लिंक नहीं कर सकते हैं, लेकिन मेरे download.php? File = आईडी गेटकीपर के माध्यम से लिंक करना है?

धन्यवाद

संपादित करें: मैं कैसे उपयोगकर्ता प्रमाणीकरण करने के लिए नहीं कह, वह सब किया जाता है। मैं सिर्फ यह पूछ रहा हूं कि ऐसा करने का मेरा तरीका, बड़े पैमाने पर एक अच्छा विचार है। ऐसा लगता है कि अगर मैं 10 जीबी फाइलें पढ़ता रहता हूं तो यह स्मृति समस्याओं का कारण बन सकता है।

उत्तर

9

ठीक है, लगभग 400 एमबी -10 जीबी की फाइल भेजना अच्छा नहीं है। आपको किसी भी तरह से वेबसर्वर का उपयोग करने की ज़रूरत है, वास्तव में फाइलों की सेवा करें।

यह वास्तव में नीचे आता है कि आपको कितना सुरक्षित होना चाहिए। सबसे आसान समाधान जो दिमाग में आता है (लेकिन सबसे सुरक्षित से बहुत दूर) मूल फ़ाइल से लिंक होने वाले लंबे यादृच्छिक नामों के साथ प्रतीकात्मक लिंक का उपयोग कर रहा है। एक निश्चित समय के बाद प्रतीकात्मक लिंक समाप्त हो जाते हैं और हटा दिए जाते हैं। प्रत्येक उपयोगकर्ता को अपना स्वयं का प्रतीकात्मक लिंक (या "टोकन") फ़ाइल डाउनलोड करने के लिए मिलता है। मुझे यकीन नहीं है कि यह विंडोज-पर्यावरण में कैसे खेलता है, लेकिन यूनिक्स पर यह वैसे भी काफी सरल है।

if($user->isAllowedToDownload($file)){ 
    $token = md5($user->name . $file->name . time() . $someGoodRandomValue); 
    symlink($file, $download_path . $token); 
    header("Location: $download_url$token"); 
} 

तो फिर तुम एक क्रॉन जॉब है कि पुराने सांकेतिक लिंक की सफाई की जरूरत है:

यहाँ कुछ छद्म कोड है। आपको यह सुनिश्चित करने की भी आवश्यकता है कि वेबसर्वर प्रतीकात्मक लिंक का पालन करने के लिए सेट है, अधिमानतः केवल उस फ़ोल्डर के लिए जहां इन डाउनलोड टोकन बनाए जाते हैं।

तो जब उपयोगकर्ता domain.com/download?file=bigfile.mp4 अनुरोध करता है तो वेबसर्वर सार्वजनिक स्थान में एक प्रतीकात्मक लिंक बनाया गया है जो वेबसर्वर सार्वजनिक स्थान के बाहर वास्तविक फ़ाइल को इंगित करता है। उपयोगकर्ता को domain.com/getFile/ab739babec890103bdbca72 पर रीडायरेक्ट किया जाता है जो बदले में वेबसर्वर फ़ाइल की सेवा करता है। अब उपयोगकर्ताओं के लिए फ़ाइल के लिए एक यूआरएल क्या है, यह अनुमान लगाने और अनुमान लगाने के लिए बहुत मुश्किल है, और यह "सुरक्षा" है।

+0

मुझे लगता है कि तुम भी कुछ सेकंड के बाद फ़ाइल (यहाँ, लिंक) अनलिंक कर सकते हैं, मैं वर्तमान डाउनलोड के लिए काम करेंगे। जैसे ही आप फ़ाइल बना सकते हैं, इसे खोलें, हटाएं, फिर इसे पढ़ें। – Aif

+0

उसे नहीं पता था, शांत! आपको यह जांचना होगा कि यह उपयोगकर्ताओं को डाउनलोड निरस्त करने और फिर से शुरू करने के साथ कैसे काम करता है। (फ़ाइलों के साथ इस बड़े मुझे लगता है कि हम डाउनलोड यह मान सकते हैं बाधित होगा हो?) – 0scar

+1

तुम भी कुकीज़ में दुकान टोकन कर सकते हैं और नियम जो फ़ाइल पथ में कुकी परिणत हो गया फिर से लिखने की है। यदि आप कुकी सेट नहीं हैं या सिमलिंक मौजूद नहीं है तो आप मूल फ़ाइल नामों के साथ अच्छे यूआरएल प्राप्त कर सकते हैं और PHP स्क्रिप्ट दिखा सकते हैं। – Ski

1

आप किसी भी तरह से उन्हें प्रमाणित करना चाहते हैं (एक HTML फॉर्म, HTTP basic auth, जो भी हो), फिर session ध्वज सेट करें, जो आपकी download.php स्क्रिप्ट जांच सकती है। ध्यान दें कि यह लोगों को फ़ाइल डाउनलोड करने से नहीं रोकता है, फिर इसे स्वयं वितरित करता है।

आपको अपने वेब सर्वर को कॉन्फ़िगर करना चाहिए ताकि वास्तविक फ़ाइलें सीधे पहुंच योग्य न हों।

यह प्रति मेमोरी समस्याओं का कारण नहीं बन रहा है। readfile फ़ाइल को स्मृति में नहीं पढ़ता है। हालांकि, PHP का उपयोग ओवरहेड बनायेगा। आप X-Sendfile का उपयोग करके इस देरी में से कुछ को खत्म कर सकते हैं।

2

आप पहले से ही ऐसा कर रहे हैं - $public_filename वह है जिसे आप इसे चाहते हैं, readfile ($ file_path) भाग फ़ाइल है - इसका स्थान सार्वजनिक नहीं किया गया है। पिछले, यह दस्तावेज़ रूट से ऊपर हो सकता है।

+0

मैं समझता हूँ .. लेकिन क्या इम पर हो रही है। ... क्या उपयोगकर्ताओं को पास करने के लिए PHP को 10 जीबी फाइलें पढ़ने का अच्छा विचार है? –

1
  1. फ़ाइलों को कहीं भी रखें जो HTTP के माध्यम से उपलब्ध नहीं है।
  2. फ़ाइल पथों के साथ फ़ाइल आईडी की डेटाबेस तालिका बनाएं।
  3. फ़ाइल आईडी के माध्यम से फ़ाइलों से लिंक करें (जैसा आपने ऊपर बताया है, download.php? FileID = 0000)।
  4. ???
  5. लाभ।

जैसा कि पहले किया गया था (कई साल पहले), आपको अपने सर्वर पर होने वाले मेमोरी प्रभाव पर विचार करने की आवश्यकता है। readfile फ़ंक्शन तब उपलब्ध नहीं था, इसलिए यह संभव है कि आपको स्मृति विचारों के लिए कुछ भी विशेष करने की आवश्यकता न हो।

1

स्मृति समस्याओं का कारण होगा आपका विधि, लेकिन यह पढ़ सकते हैं और उत्पादन के लिए मात्रा में फ़ाइल संभव है। आप फ़ाइल के echo प्रत्येक हिस्सा आप के बाद flush() फ़ंक्शन का उपयोग करने की आवश्यकता होगी। आप थोड़ा और प्रयास के साथ काम करने के लिए फिर से शुरू करने के डाउनलोड भी कर सकते हैं। फिर भी यह एक सीपीयू भूख दृष्टिकोण है।

आसान और बेहतर समाधान "एक्स Sendfile" शीर्षक टैग दोनों अपाचे और lighttpd उनके मॉड्यूल के माध्यम से द्वारा समर्थित उपयोग करने के लिए है। आपको बस इतना करना होगा बस अपने शीर्षक, इस के समान में फ़ाइल नाम निर्दिष्ट किया जाता है: lighttpd के लिए

header('X-Sendfile: filename-on-your-file-system'); 

लिंक:

http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file

संबंधित मुद्दे

 संबंधित मुद्दे