Advertisement
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

[New API] Download file from plugin

Comments in 'Plugin Development' started by Adaasi, Dec 3, 2014.

  1. Adaasi
    Offline

    Adaasi Active Member

    Joined:
    Aug 14, 2014
    Posts:
    78
    How can I make a plugin that download a file from a given link?
  2. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    Use pocketmine\utils\Utils::getURL() if you want to download and process the data like JSON or other APIs. You can also file_put_contents() the result.
    You can also use copy("http://example.com", "one.file") to copy, as long as the connection is not HTTPS. If it is HTTPS, you must use cURL (Utils::getURL()).

    Remember, this call usually takes more than 0.1 second, which is considered as "slow" and "blocking", and should be run in an AsyncTask or a separate Thread. Blocking calls take more than one tick, and they will "overload" the server. Always use an AsyncTask when doing these things.
    Adaasi, hoyinm14mc and EvolSoft like this.
  3. iksaku
    Offline

    iksaku Notable Member Plugin Developer

    Joined:
    Sep 2, 2013
    Posts:
    1,130
    Plugins:
    4
    Minecraft User:
    iksaku
    Could you help me to implement an updater on EssentialsPE? :3 over the "/essentials" command :p
    PEMapModder likes this.
  4. Adaasi
    Offline

    Adaasi Active Member

    Joined:
    Aug 14, 2014
    Posts:
    78
    Thanks. But I have another question. How can I know when the download is finished?
  5. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    As I said, it is a thread-blocking operation. That means the line after the function won't be executed (and the whole server will hibernate except other threads) until the download ends. That's why you have to use an AsyncTask.
    Example plugin:
    (Will post later)
    Adaasi and EvolSoft like this.
  6. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    plugin.yml:
    Code:
    name: Downloader
    author: PEMapModder
    version: 0.0
    api: 1.0.0
    main: downloader\DownloaderPlugin
    commands:
      dl:
        usage: /dl <URL> <name>
        description: Downloads a file from <URL> to plugin data folder/<name>
    src/downloader/DownloaderPlugin.php:
    PHP:
    <?php
    namespace downloader;
    class 
    DownloaderPlugin extends \pocketmine\plugin\PluginBase{
      public function 
    onCommand(\pocketmine\command\CommandSender $sender, \pocketmine\command\Command $c$l, array $args){
        
    // missing: only execute the following code after confirming $c->getName() is "dl"
        
    if(!isset($args[1])) return false// if not enough arguments, send usage and exit command
        
    $to $this->getDataFolder() . "downloads/$args[1]";
        @
    mkdir(dirname($to), 0777true); // create the directory for the file to be saved if it doesn't already exist
        
    $this->getServer()->getScheduler()->scheduleAsyncTask(new DownloadTask($args[0], $this->getDataFolder() . $args[1], $this$sender)); // add the AsyncTask to the server scheduler's async task pool
      
    }
    }
    src/downloader/DownloadTask.php:
    PHP:
    <?php
    namespace downloader;
    class 
    DownloadTask extends \pocketmine\scheduler\AsyncTask{
      private 
    $from$to;
      private 
    $plugin;
      private 
    $sender;
      public function 
    __construct($from$toDownloaderPlugin $plugin, \pocketmine\command\CommandSender $sender){
        
    // initialize fields
        
    $this->from $from;
        
    $this->to $to;
        
    $this->plugin $plugin;
        
    $this->sender $sender;
      }
      public function 
    onRun(){
        
    $start microtime(true);
        
    $result = \pocketmine\utils\Utils::getURL($this->from); // download data from the URL. This function call blocks.
        
    $end microtime(true);
        
    // ($end - $start) is the number of seconds (decimal numbers) used to download data.
        
    if(!is_string($result)){
          
    $this->setResult(false); // if $result is not a string, the download must have failed. Set the result to false to remember that it failed.
          
    return;
        }
        
    file_put_contents($this->to$result); // save $result to the target file
        
    $this->setResult(true); // Set the result to true to remember that it has success.
      
    }
      public function 
    onCompletion(\pocketmine\Server $server){
        if(
    $this->getResult() === true){ // upon success
          
    $this->sender->sendMessage("File downloaded from $this->from, saved at $this->to");
        }else{ 
    // upon failure
          
    $this->sender->sendMessage("For some reason, downloading from $this->from to $this->to failed.");
        }
      }
    }
  7. EvolSoft
    Offline

    EvolSoft Notable Member Plugin Developer

    Joined:
    Sep 10, 2014
    Posts:
    821
    Plugins:
    15
    Minecraft User:
    Flavius12
    Great example @PEMapModder :)
    Adaasi likes this.

Share This Page

Advertisement