How to download zip file from url and save it on writable directory with cocos2d-x v3.11

Hi,
i would like to download a zip file from server and store it on writable directory,
i’m using cocos2d-x v3.11.
my zip file size is about 70 MB…
Please help me.
Any suggestions are appreciated.
Thanks

1 Like

You can use network::Downloader class. Here code example:

std::string url = "http://www.colorado.edu/conflict/peace/download/peace.zip";
std::string filePath = FileUtils::getInstance()->getWritablePath() + "peace.zip";

network::Downloader *downloader = new (std::nothrow) network::Downloader();

downloader->onTaskProgress = ([] (const network::DownloadTask& task, int64_t bytesReceived, int64_t totalBytesReceived, int64_t totalBytesExpected) {
    //downloading progress
});

downloader->onFileTaskSuccess = ([] (const network::DownloadTask& task) {
    //file downloaded, do what you need next
});

downloader->onTaskError = ([] (const network::DownloadTask& task, int errorCode, int errorCodeInternal, const std::string& errorStr) {
    //file downloading error
});

downloader->createDownloadFileTask(url, filePath);

lambdas are optional, but i recommend use it, or use CC_CALLBACK instead.

3 Likes

not working…it start download…but…after starting download every time got error… :frowning:

What error? You can see error info by CCLOG like this

downloader->onTaskError = ([] (const network::DownloadTask& task, int errorCode, int errorCodeInternal, const std::string& errorStr) {
    //file downloading error
    CCLOG("download failed with error: %s error code: %i error code internal: %i", errorStr.c_str(), errorCode, errorCodeInternal);
});

But first try download your .zip file with your link in browser. I tested my example on linux and android, peace.zip downloads great.

You could also use cUrl but @Capone has a great solution too.

I also tried it on mac, and this time i take huge file - cocos2d-x version 3.12 zip! It took time, but finally archive was downloaded.

Your code does work :slight_smile:

Big Thanks To CAPONE… its work :smiley:

it is worked in IOS but got error in Android…

-pre-compile:

-compile:
[javac] Compiling 28 source files to /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/bin/classes
[javac] warning: [options] source value 1.5 is obsolete and will be removed in a future release
[javac] warning: [options] target value 1.5 is obsolete and will be removed in a future release
[javac] warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:9: error: package org.apache.http does not exist
[javac] import org.apache.http.Header;
[javac] ^
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:10: error: package org.apache.http.message does not exist
[javac] import org.apache.http.message.BasicHeader;
[javac] ^
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:47: error: cannot find symbol
[javac] public void onFailure(int i, Header[] headers, byte[] errorResponse, Throwable throwable) {
[javac] ^
[javac] symbol: class Header
[javac] location: class DataTaskHandler
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:57: error: cannot find symbol
[javac] public void onSuccess(int i, Header[] headers, byte[] binaryData) {
[javac] ^
[javac] symbol: class Header
[javac] location: class DataTaskHandler
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:106: error: cannot find symbol
[javac] public void onFailure(int i, Header[] headers, Throwable throwable, File file) {
[javac] ^
[javac] symbol: class Header
[javac] location: class FileTaskHandler
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:116: error: cannot find symbol
[javac] public void onSuccess(int i, Header[] headers, File file) {
[javac] ^
[javac] symbol: class Header
[javac] location: class FileTaskHandler
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:253: error: cannot find symbol
[javac] Header[] headers = null;
[javac] ^
[javac] symbol: class Header
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:257: error: cannot find symbol
[javac] List list = new ArrayList();
[javac] ^
[javac] symbol: class Header
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:257: error: cannot find symbol
[javac] List list = new ArrayList();
[javac] ^
[javac] symbol: class Header
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:258: error: cannot find symbol
[javac] list.add(new BasicHeader(“Range”, “bytes=” + fileLen + “-”));
[javac] ^
[javac] symbol: class BasicHeader
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:259: error: cannot find symbol
[javac] headers = list.toArray(new Header[list.size()]);
[javac] ^
[javac] symbol: class Header
[javac] /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java:261: error: cannot access HttpEntity
[javac] task.handle = downloader._httpClient.get(Cocos2dxHelper.getActivity(), url, headers, null, task.handler);
[javac] ^
[javac] class file for org.apache.http.HttpEntity not found
[javac] Note: Some input files use or override a deprecated API.
[javac] Note: Recompile with -Xlint:deprecation for details.
[javac] Note: /Users/shaktirajsinhjadeja/Desktop/cocos2d-x-3.12/santiJunior/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java uses unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.
[javac] 12 errors
[javac] 3 warning

org.apache.http was removed from SDK 23. To fix your problem, look here:

Most of the fix instructions are for gradle, but I guess you’re using Ant-- in that case, you can find the jar file in android-sdk/platforms/android-23/optional … probably copying that into your libs/ directory would work.

1 Like

i used Eclipse/ADT now and i successfully compiling project…
but after i run project … its give following error… :expressionless:

download failed with error: javax.net.ssl.SSLException:
hostname in certificate didn’t match: <tecjuniours.in> !=
<.prod.sin2.secureserver.net> OR
<
.prod.sin2.secureserver.net> OR
<prod.sin2.secureserver.net> error code: -3 error code internet:0

thanks in advance…

its works… :smile:
actually issue was server side…
thank you all … specially thanks to CAPONE :blush:

To use network extension, you have to do this:
#include “cocos-ext.h”

1 Like

Hi @CAPONE
I want to cancel downloader task . How to cancel downloading task progress ?

You just can try destroy DownloadTask instance inside onTaskProgress. Then destroy Downloader instance then remove file part by FileUtils.

@CAPONE
I have a download later button when user pressed on this button i want to cancel downloader task
and my code for this is
downlater is a boolean value


 downloader = new (std::nothrow) network::Downloader();

  downloader->onTaskProgress = ([this](const network::DownloadTask& task, int64_t bytesReceived, int64_t totalBytesReceived, int64_t totalBytesExpected) {
    CCLOG("downloading progress........!!!!!!!!");

    if (!downloadLater){

    downloadPercent = float(totalBytesReceived * 100) / totalBytesExpected;

    // Convert percent to String and set as label
    char buf[32];
    sprintf(buf, "%.0f%%", downloadPercent, int(totalBytesExpected / 1024));
    auto status = (Label*)downloadingProgressLayer->getChildByTag(11);

    status->setString(buf);
    } else {
      CCLOG("Download later buttton pressed");
      // Delete downloader task instance
      delete &task;
      // delete downloader instance
      delete downloader;
     // Delete file using FileUtils
      FileUtils::getInstance()->removeFile(FileUtils::getInstance()->getWritablePath() + "Story");
    }
  });

But app is crashed, am i doing something wrong ?

Ok, for example you have class MyClass for downloading file, here code example.

On header of your class:

class MyClass
{
public:
    
    ...

    virtual void startDownload();
    
    virtual void cancelDownload();

private:

    bool _downloadRunning;

    cocos2d::network::Downloader *_downloader;
    std::shared_ptr<const cocos2d::network::DownloadTask> _task;
};

On .cpp of you class

MyClass::init() {

     ...

     _downloadRunning = false;

     _downloader = nullptr;
     _task = nullptr;
}

MyClass::startDownload() {
     std::string url = "http://cdn.cocos2d-x.org/cocos2d-x-3.15.1.zip";
     std::string filePath = FileUtils::getInstance()->getWritablePath() + "cocos2d-x-3.15.1.zip";

     _downloader = new (std::nothrow) network::Downloader();

     _downloader->onTaskProgress = ([](const network::DownloadTask& task, int64_t bytesReceived, int64_t totalBytesReceived, int64_t totalBytesExpected) {
          CCLOG("download progress %.0f%%", (float) totalBytesReceived * 100.0 / totalBytesExpected );
	});

     _downloader->onFileTaskSuccess = ([this](const network::DownloadTask& task) {
          CCLOG("downloaded success");

          delete _downloader;
          _downloader = nullptr;
          _task = nullptr;
          _downloadRunning = false;
	});

     _downloader->onTaskError = ([](const network::DownloadTask& task, int errorCode, int errorCodeInternal, const std::string& errorStr) {
	          CCLOG("downloading error %s", errorStr.c_str());
	});

     _task = _downloader->createDownloadFileTask(url, filePath);

     _downloadRunning = true;

     CCLOG("download started");
}

MyClass::cancelDownload() {
if (_downloadRunning) {
     CCLOG("canceling download...");
			
     std::string path = _task->storagePath;
     delete _downloader;
     _downloader = nullptr;
     _task = nullptr;
     _downloadRunning = false;
     if (FileUtils::getInstance()->removeFile(path + ".tmp")) CCLOG("download canceled");
     }
}

.tmp suffix defined by default but you can change it by DownloaderHints.

Thanks @CAPONE

Hey, sorry to revive an old thread, but @slackmoehrle suggested I check this out, and it looks great! I’m trying to download a zip file from my google drive, a folder that I made viewable (now, it’s view only to the public, so I don’t know if that’s an issue).

When I try to download, I get this error:
ERROR downloading, errorCode = -3 (60): Peer certificate cannot be authenticated with given CA certificates

I’m taking that path and simply appending a slash and the filename.

** By the way, I can download the cocos2d-x zip file, so it’s something to do with trying to pull from a shared google drive. Oh, when downloading the cocos2d-x zip file, “expectedTotalBytes” stayed zero the whole time.

Here’s my code (once I get it working, I’ll create a full-blown class):

   string location = "https://drive.google.com/drive/folders/1U2XTP3acCPxgxdzZi3kJ63dxqpmlg3mC";
  string defLeague = "2019_league_test.lgs";
  string realLeague = "2019_league real_names.lgs";
  string localPath = getPsfWritablePath();
  string filePath;
  
  // make sure the location has a trailing slash
  appendSlash(location);
  appendSlash(localPath);

  string url = location + defLeague;
  filePath = localPath + defLeague;

  network::Downloader *downloader = new (std::nothrow) network::Downloader();
  downloader->onTaskProgress = ([] (const network::DownloadTask &task, int64_t bytesReceived, int64_t totalBytesReceived, int64_t totalBytesExpected) {
      CCLOG("onTaskProgress, downloaded %d of %d", totalBytesReceived, totalBytesExpected);
      // downloading progress
    });

  downloader->onFileTaskSuccess = ([] (const network::DownloadTask &task) {
      CCLOG("File downloaded!  Now do stuff");
    });

  downloader->onTaskError = ([] (const network::DownloadTask &task, int errorCode, int errorCodeInternal, const std::string& errorStr) {
      CCLOG("ERROR downloading, errorCode = %d (%d): %s", errorCode, errorCodeInternal, errorStr.c_str());
      //file downloading error
    });

  downloader->createDownloadFileTask(url, filePath);