2011-03-10 10 views
20

मेरे पास एक बहुत ही सरल सवाल है: PHP में फ़ाइल डाउनलोड करने का सबसे अच्छा तरीका क्या है, लेकिन केवल 5 मिनट पहले स्थानीय संस्करण डाउनलोड किया गया है?PHP में 5-मिनट फ़ाइल कैश

मेरे वास्तविक मामले में मैं एक दूर की मेजबानी csv फ़ाइल से डेटा प्राप्त करने के लिए मैं वर्तमान में किसी भी स्थानीय प्रतिलिपि या कैशिंग के बिना

$file = file_get_contents($url); 

का उपयोग करना चाहते हैं। इसे कैश किए गए संस्करण में बदलने का सबसे आसान तरीका क्या है, जहां अंतिम परिणाम नहीं बदलता है ($ फ़ाइल वही रहता है), लेकिन यह स्थानीय प्रतिलिपि का उपयोग करता है यदि इसे बहुत पहले नहीं लिया गया था (5 मिनट कहें)?

उत्तर

49

एक स्थानीय कैश फ़ाइल का उपयोग करें, और बस की जाँच फ़ाइल का उपयोग करने से पहले फ़ाइल पर अस्तित्व और संशोधन समय। उदाहरण के लिए, यदि $cache_file एक स्थानीय कैश फ़ाइल नाम है:

if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 5))) { 
    // Cache file is less than five minutes old. 
    // Don't bother refreshing, just use the file as-is. 
    $file = file_get_contents($cache_file); 
} else { 
    // Our cache is out-of-date, so load the data from our remote server, 
    // and also save it over our cache for next time. 
    $file = file_get_contents($url); 
    file_put_contents($cache_file, $file, LOCK_EX); 
} 

(। untested है, लेकिन कोड मैं इस समय का उपयोग के आधार पर)

इस कोड के माध्यम से

किसी भी तरह से, $ फ़ाइल को डेटा के रूप में समाप्त होता है आप आवश्यकता है, और यह या तो ताजा होने पर कैश का उपयोग करेगा, या दूरस्थ सर्वर से डेटा ले जाएगा और यदि नहीं तो कैश रीफ्रेश करें।

संपादित करें: मैं उपरोक्त लिखने के बाद से फ़ाइल लॉकिंग के बारे में थोड़ा और समझता हूं। यदि आप यहां लॉकिंग फ़ाइल के बारे में चिंतित हैं तो this answer के पढ़ने के लायक हो सकता है।

आप ताला और समवर्ती पहुँच के बारे में चिंतित हैं, तो मैं कहेंगे साफ समाधान एक अस्थायी फाइल करने के लिए file_put_contents होगा, तो rename() यह $cache_file से अधिक है, जो एक परमाणु आपरेशन होना चाहिए, यानी $cache_file होगा या तो पुरानी सामग्री या पूर्ण नई सामग्री हो, कभी भी आधा रास्ते लिखा नहीं है।

+0

कोड मैट के लिए धन्यवाद! यह बहुत साफ है, अच्छी तरह से टिप्पणी की है और बिना किसी संशोधन के काम करता है! – zsero

+0

@ ज़ेसरो कूल। लेकिन वहां कुछ त्रुटि जांचें :) यदि आप वेब सर्वर उपयोगकर्ता द्वारा कैश निर्देशिका लिखने योग्य नहीं हैं, तो आप समस्याओं में भाग सकते हैं, उदाहरण के लिए ... –

+1

हाँ इसे कुछ त्रुटि जांच की आवश्यकता हो सकती है लेकिन इसकी ऐसी छोटी परियोजना है इस कोड का उपयोग या तैनाती कोई और नहीं होगा। और यदि यह टूट गया है तो दूसरा हिस्सा वास्तव में ब्रेक करने की बजाए कैश-कम मोड में जाता है। अच्छा लगा। – zsero

-1

आप अपनी फ़ाइल की एक प्रति पहली हिट पर सहेज सकते हैं, फिर फ़ाइल हिट के साथ स्थानीय हिट के अंतिम संशोधन के टाइमस्टैम्प को निम्न हिट पर जांचें।

0

यदि आप किसी भी प्रकार की डेटाबेस सिस्टम का उपयोग कर रहे हैं, तो आप इस फ़ाइल को कैश कर सकते हैं। कैश की गई जानकारी के लिए एक टेबल बनाएं, और इसे कम से कम निम्न फ़ील्ड दें:

  • एक पहचानकर्ता; अगली बार जब आपको इसकी आवश्यकता हो तो फ़ाइल को पुनः प्राप्त करने के लिए आप इसका उपयोग कर सकते हैं। शायद फ़ाइल नाम की तरह कुछ।
  • पिछली बार जब आपने URL से फ़ाइल डाउनलोड की थी, तब से एक टाइमस्टैम्प।
  • या तो फ़ाइल के लिए एक पथ, जहां यह आपके स्थानीय फाइल सिस्टम में संग्रहीत है, या बस फ़ाइल में सामग्री की सामग्री को संग्रहीत करने के लिए एक बीएलओबी प्रकार फ़ील्ड का उपयोग करें। मैं व्यक्तिगत रूप से पथ को संग्रहीत करने की सिफारिश करता हूं। अगर फ़ाइल बहुत बड़ी थी, तो आप निश्चित रूप से इसे डेटाबेस में नहीं रखना चाहेंगे।

अब, जब आप अगली बार ऊपर स्क्रिप्ट चलाते हैं, तो पहले पहचानकर्ता के लिए डेटाबेस में जांचें, और टाइम स्टैंप खींचें। यदि वर्तमान समय और संग्रहीत टाइमस्टैम्प के बीच का अंतर URL से 5 मिनट से अधिक है और डेटाबेस को अद्यतन करता है। अन्यथा, डेटाबेस से फ़ाइल लोड करें।

यदि आपके पास डेटाबेस सेटअप नहीं है, तो आप फ़ाइलों का उपयोग करके वही काम कर सकते हैं, जिसमें एक फ़ाइल या फ़ाइल में फ़ील्ड में फ़ाइल को आखिरी बार डाउनलोड करने के समय से टाइमस्टैम्प होगा।

-2

मुझे लगता है कि आप की तरह कुछ (छद्म कोड) तर्क हैं:

if ($file exists) { 
    if ($file time stamp older than 5 minutes) { 
    $file = file_get_contents($url) 
    } 
} else { 
    $file = file_get_contents($url) 
} 

use $file 
+2

मुझे समझ नहीं आता, अंत किसी और एक ही ... – zsero

+0

@zsero .. लगता है अगर अतिरिक्त परत क्योंकि आप एक फ़ाइल जो मौजूद नहीं है की समय स्टाम्प परीक्षण नहीं कर सकते वहाँ में है। –

-1

आप इसे विधि की तरह एक कैश में ताना होगा:

function getFile($name) { 
    // code stolen from @Peter M 
    if ($file exists) { 
     if ($file time stamp older than 5 minutes) { 
     $file = file_get_contents($url) 
     } 
    } else { 
     $file = file_get_contents($url) 
    } 
    return $file; 
} 
+1

पीटर एम के जवाब के साथ, मुझे नहीं पता कि क्यों और क्यों वही है? – zsero

0

सबसे पहले, आप डिज़ाइन पैटर्न को देखना चाहते हैं: Lazy loading

कार्यान्वयन को हमेशा स्थानीय कैश से फ़ाइल लोड करने के लिए बदलना चाहिए। यदि स्थानीय कैश मौजूद नहीं है या फ़ाइल समय जिटर 5 मिनट से अधिक लंबा है, तो आप फ़ाइल को सर्वर से लाते हैं।

छद्म कोड निम्नलिखित की तरह है:

$time = filetime($local_cache) 
if ($time == false || (now() - $time) > 300000) 
    fetch_localcache($url) #You have to do it yourself 
$file = fopen($local_cache) 
7

प्रयास करें phpFastCache, इसे समर्थन फ़ाइलों कैशिंग, और आप अपने कैश वर्ग कोड करने के लिए जरूरत नहीं है।

<?php 

// change files to memcached, wincache, xcache, apc, files, sqlite 
$cache = phpFastCache("files"); 

$content = $cache->get($url); 

if($content == null) { 
    $content = file_get_contents($url); 
    // 300 = 5 minutes 
    $cache->set($url, $content, 300); 
} 

// use ur $content here 
echo $content; 
+0

क्या आप यह देखने के लिए बेंचमार्क चला सकते हैं कि क्या प्रोग्राम कैशिंग के साथ सिद्धांत या कैश तेज है या phpFastCache है? – user4271704

0

यहाँ एक सरल संस्करण है जो भी एक खिड़कियों दूरस्थ होस्ट से User-Agent स्ट्रिंग से गुजरता है तो आप एक मुसीबत निर्माता की तरह लग रही नहीं है: साझा होस्टिंग पर इस्तेमाल करने में आसान और VPS

यहाँ उदाहरण है उचित शीर्षलेख के बिना।

<?php 

function getCacheContent($cachefile, $remotepath, $cachetime = 120){ 

    // Generate the cache version if it doesn't exist or it's too old! 
    if(! file_exists($cachefile) OR (filemtime($cachefile) < (time() - $cachetime))) { 

     $options = array(
      'method' => "GET", 
      'header' => "Accept-language: en\r\n" . 
      "User-Agent: Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)\r\n" 
     ); 

     $context = stream_context_create(array('http' => $options)); 
     $contents = file_get_contents($remotepath, false, $context); 

     file_put_contents($cachefile, $contents, LOCK_EX); 
     return $contents; 

    } 

    return file_get_contents($cachefile); 
} 
संबंधित मुद्दे