Kirix Support Forums

Implementing download listener

Please post all general questions, comments, bug reports, and any other wxWebConnect feedback here.

Implementing download listener

Postby mgsutton on Tue Aug 11, 2009 6:21 pm

Hey Guys,
Does anyone have any pointers on how to implement a download listener? It looks like in the example app if a user initiates a download and then navigates away from the page before the download completes, the download is only partially retrieved. So, I'm poking through the webcontrol.h file, and looking at the wxWebEvent and the wxWebProgressBase classes. It looks like they are implemented in the header file. So, I'm trying to piece together how one would go about hooking up a control that will allow the user to initiate a download and then navigate away from the page while still keeping the download alive. I guessing here, but would you create a new hidden wxWebControl and pass it the file url, monitor events in it to determine when the download completed, stopping, etc...? Is this what the SetCreateBrowser(...) is for? Or am I completely missing it altogether. Any help would be appreciated!!
Thanks,
Matt
mgsutton
Registered User
 
Posts: 4
Joined: Fri Jul 24, 2009 4:08 pm

Re: Implementing download listener

Postby Aaron on Wed Aug 12, 2009 11:17 am

Downloads are handled in the background, so you shouldn't have problems with "partially downloaded" files unless the operation fails or is cancelled.

To implement a download listener, create a derived class from wxWebProgressBase:

Code: Select all
class DownloadProgressListener : public wxWebProgressBase
{
public:

    DownloadProgressListener()
    {
    }

    virtual void Init(const wxString& url,
                      const wxString& suggested_filename)
    {
        m_url = url;
        m_filename = suggested_filename;
    }

    virtual void OnStart()
    {
    }

    virtual void OnFinish()
    {
        // cleanup
        delete this;
    }
   
    virtual void OnError(const wxString& message)
    {
    }
   
    virtual void OnProgressChange(wxLongLong cur_progress,
                                  wxLongLong max_progress)
    {
        // TODO: if the operation is cancelled, call Cancel()
    }
   
private:

    wxString m_url;
    wxString m_filename;
};


Then, once you've created this class, you can use it to handle downloads in the EVT_WEB_INITDOWNLOAD event handler:

Code: Select all
// web event ID:
const int wxID_WEB = 9001;

// add following to event table:
EVT_WEB_INITDOWNLOAD(wxID_WEB, MyFrame::OnInitDownload)

// event handler:
void MyFrame::OnInitDownload(wxWebEvent& evt)
{
    // TODO: add download status indicator and option
    // to open content in the browser

    // note: this handler gets called when content is
    // available to download; the content can be handled
    // as follows:
    //   evt.SetDownloadAction(wxWEB_DOWNLOAD_OPEN);   // open content
    //   evt.SetDownloadAction(wxWEB_DOWNLOAD_SAVEAS); // save content
    //   evt.SetDownloadAction(wxWEB_DOWNLOAD_CANCEL); // cancel the operation

    // here, we'll allow the user to download it or cancel
    // the operation

    // get the filename
    wxString filename = evt.GetFilename();
    wxMessageDialog dlg(this,
                        wxString::Format(wxT("Would you like to download %s?"), filename),
                        wxT("Download File"),
                        wxYES_NO);

    int result = dlg.ShowModal();

    switch (result)
    {
        case wxID_YES:
            {
                wxString filter;
                filter += _("All Files");
                filter += wxT(" (*.*)|*.*");

                wxFileDialog dlg(this,
                         _("Save As"),
                         wxT(""),
                         filename,
                         filter,
                         wxFD_SAVE | wxFD_OVERWRITE_PROMPT);

                if (dlg.ShowModal() != wxID_OK)
                {
                    evt.SetDownloadAction(wxWEB_DOWNLOAD_CANCEL);
                    return;
                }

                // destroyed in DownloadProgressListener::OnFinish()
                DownloadProgressListener* listener = new DownloadProgressListener;
                evt.SetDownloadAction(wxWEB_DOWNLOAD_SAVEAS);
                evt.SetDownloadTarget(dlg.GetPath());
                evt.SetDownloadListener(listener);
            }
            break;

        case wxID_NO:
            evt.SetDownloadAction(wxWEB_DOWNLOAD_CANCEL);
            break;
    }
}


Alternatively, you can download a file programmatically, such as you might do from a "Save Link As" context menu item:

Code: Select all
bool MyFrame::DownloadFile(const wxString& url,
                           const wxString& filename)
{
    DownloadProgressListener* listener = new DownloadProgressListener;
    return wxWebControl::SaveRequest(url, filename, NULL, listener);
}
Aaron Williams
Kirix Support Team
User avatar
Aaron
Kirix Support Team
 
Posts: 120
Joined: Fri Dec 16, 2005 3:01 pm

Return to wxWebConnect Questions, Thoughts & Feedback