利用curl下载文件(进度条显示) 代码片段

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://axiii.blog.51cto.com/396236/112836
在 项目中需要用到程序更新的功能,同事介绍说是curl中的开发库很牛x,又是跨平台(他们总是这么喜欢跨平台的东西 *_*),于是下载这个包测试了一下,确实不错。准备正式用到项目中,以下一个例子用于从互联网上抓取一个文件下载到本地,并加上进度条显示,做得挺简 陋,不过功能差不多就这样了。
程序运行预览.
 
首先需要加入多线程的机制,因为程序一边在下载文件,一边在显示进度条,单线程的方式肯定不行,所以我用到了wxTimer来实现,在 downloadMain.h 中定义了一个wxTimer,并做了事件申明.
DECLARE_EVENT_TABLE()

 
 
/***************************************************************
* Name:            downloadMain.h
* Purpose:     Defines Application Frame
* Author:         (alan)
* Created:     2008-11-14
* Copyright:    (谦泰通讯)
* License:
**************************************************************/


#ifndef DOWNLOADMAIN_H
#define DOWNLOADMAIN_H



#include "downloadApp.h"


#include <wx/timer.h>
#include "GUIDialog.h"

class downloadDialog: public GUIDialog
{
         public:
                downloadDialog(wxDialog *dlg);
                ~downloadDialog();
                 void OnTimer(wxTimerEvent& event);
         private:
                 virtual void OnClose(wxCloseEvent& event);
                 virtual void OnQuit(wxCommandEvent& event);
                 virtual void OnAbout(wxCommandEvent& event);
                 void downloadfile();
                wxTimer* m_timerdown;
                DECLARE_EVENT_TABLE()
};
#endif // DOWNLOADMAIN_H
 
下面是主程序的代码.
/***************************************************************
* Name:            downloadMain.cpp
* Purpose:     Code for Application Frame
* Author:         (alan)
* Created:     2008-11-14
* Copyright:    (谦泰通讯)
* License:
**************************************************************/


#ifdef WX_PRECOMP
#include "wx_pch.h"
#endif

#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__

#include "downloadMain.h"
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include "update.h"
#include <wx/msgdlg.h>
#include <wx/utils.h>
#define TIMER_ID 22222
//事件监听声明
BEGIN_EVENT_TABLE(downloadDialog, GUIDialog)
        EVT_TIMER(TIMER_ID, downloadDialog::OnTimer)
END_EVENT_TABLE()

enum wxbuildinfoformat
{
        short_f, long_f
};

wxString wxbuildinfo(wxbuildinfoformat format)
{
        wxString wxbuild(wxVERSION_STRING);

         if (format == long_f )
        {
# if defined(__WXMSW__)
                wxbuild << _T( "-Windows");
#elif defined(__WXMAC__)
                wxbuild << _T( "-Mac");
#elif defined(__UNIX__)
                wxbuild << _T( "-Linux");
#endif

# if wxUSE_UNICODE
                wxbuild << _T( "-Unicode build");
# else
                wxbuild << _T( "-ANSI build");
#endif // wxUSE_UNICODE
        }

         return wxbuild;
}

//声明一个文件结构体
struct FtpFile
{
         char *filename;
        FILE *stream;
};

downloadDialog::downloadDialog(wxDialog *dlg)
                : GUIDialog(dlg)
{

         //创建一个定时器,制定TIMER_ID
        m_timerdown = new wxTimer( this, TIMER_ID);
         //定时器开始运行,这里会自动执行OnTimer函数
        m_timerdown->Start(100);
}

downloadDialog::~downloadDialog()
{

}
//定时器操作
void downloadDialog::OnTimer(wxTimerEvent & event)
{
        downloadfile();
}
//文件写入流
int my_fwrite( void *buffer, size_t size, size_t nmemb, void *stream)
{
         struct FtpFile * out=( struct FtpFile *)stream;
         if ( out && ! out->stream)
        {
                 out->stream=fopen( out->filename, "wb");
                 if (! out->stream)
                {
                         return -1;
                }
        }
         return fwrite(buffer, size, nmemb, out->stream);
}
//进度条显示函数
int wxcurldav_dl_progress_func( void* ptr, double rDlTotal, double rDlNow, double rUlTotal, double rUlNow)
{
                                wxGauge* pGauge = (wxGauge*) ptr;
                                 if(pGauge)
                                 //设置进度条的值
                                        pGauge->SetValue(100.0 * (rDlNow/rDlTotal));
                                 return 0;
}
//下载文件函数
void downloadDialog::downloadfile()
{
         //创建curl对象
        CURL *curl;
        CURLcode res;
        m_staticText2->SetLabel(wxT( "请耐心等待程序下载更新包..."));
         struct FtpFile ftpfile=
        {
                 //定义下载到本地的文件位置和路径
                 "tmp.exe",NULL
        };
        curl_global_init(CURL_GLOBAL_DEFAULT);

         //curl初始化
        curl = curl_easy_init();

         //curl对象存在的情况下执行操作
         if (curl)
        {
                 //设置远端地址
                curl_easy_setopt(curl, CURLOPT_URL, "http://dl_dir.qq.com/minigamefile/QQGame2008ReleaseP2_web_setup.EXE");
                //执行写入文件流操作
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
                //curl的进度条声明
                curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
                //回调进度条函数
                curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, wxcurldav_dl_progress_func);
                //设置进度条名称
                curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, m_gauge1);

                //进度条
                m_gauge1->SetValue(0);
                //写入文件
                res = curl_easy_perform(curl);
                m_gauge1->SetValue(100);
                //释放curl对象
                curl_easy_cleanup(curl);

                if (CURLE_OK != res)
                        ;
        }
        if (ftpfile.stream)
        {
                //关闭文件流
                fclose(ftpfile.stream);
        }
                //释放全局curl对象
                curl_global_cleanup();
                //这一步很重要,停止定时器,不然程序会无休止的运行下去
                m_timerdown->Stop();
                //执行刚下载完毕的程序,进行程序更新
                int pid = ::wxExecute(_T("tmp.exe"));
                wxMessageBox(wxT("下载完毕,程序开始执行更新操作......"));
}
void downloadDialog::OnClose(wxCloseEvent &event)
{
        Destroy();
}

void downloadDialog::OnQuit(wxCommandEvent &event)
{
        Destroy();
}

void downloadDialog::OnAbout(wxCommandEvent &event)
{

}
### 回答1: 这是一个PHP代码片段,可以帮助您显示下载进度条: ``` $file = "yourfile.zip"; $file_size = filesize($file); header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=$file"); header("Content-Length: $file_size"); $chunksize = 1 * (1024 * 1024); $handle = fopen($file, 'rb'); $buffer = ''; while (!feof($handle)) { $buffer = fread($handle, $chunksize); echo $buffer; ob_flush(); flush(); } fclose($handle); ``` 这段代码会在浏览器中以二进制流的形式下载文件,并显示下载进度条。 ### 回答2: 下面是一个使用PHP显示下载进度条的示例代码: ```php <?php $fileUrl = "http://example.com/file.zip"; // 下载文件的URL $saveTo = "path/to/save/file.zip"; // 下载文件保存的路径 // 启动输出缓冲区 ob_start(); // 初始化cURL会话 $ch = curl_init($fileUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 发送请求并获取文件大小 curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_exec($ch); $fileSize = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); // 关闭头部请求 curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_NOBODY, false); // 开始下载文件 $fp = fopen($saveTo, "w"); curl_setopt($ch, CURLOPT_FILE, $fp); curl_exec($ch); // 关闭cURL会话和文件句柄 curl_close($ch); fclose($fp); // 清空输出缓冲区 ob_end_flush(); echo "文件下载完成!"; ?> ``` 该代码使用cURL库来下载文件。首先,通过设置`CURLOPT_HEADER`和`CURLOPT_NOBODY`选项,我们发送一个头部请求来获取文件的大小。接着,我们关闭头部请求并设置`CURLOPT_FILE`选项来将文件内容保存到指定的文件路径中。 要显示下载进度条,我们可以在启用输出缓冲区后,追踪cURL下载进度并输出进度条到浏览器。在这个示例中,我们只是简单地在下载完成后输出一个完成的消息。 请注意,这只是一个基本示例,您可以根据自己的需求进行修改和定制。另外,为了更好的用户体验,您可能还需要添加错误处理、进度百分比计算等功能。 ### 回答3: PHP显示下载进度条代码如下所示: ```php <?php $file_url = 'http://example.com/file_to_download.zip'; // 下载文件的URL $file_name = 'file_to_download.zip'; // 下载文件保存的文件名 header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . $file_name . '"'); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($file_url)); // 读取并发送文件内容 $handle = fopen($file_url, 'rb'); $buffer_size = 8192; // 每次读取的字节数 $bytes_sent = 0; while (!feof($handle) && !connection_aborted()) { $buffer = fread($handle, $buffer_size); echo $buffer; flush(); $bytes_sent += strlen($buffer); // 计算并显示下载进度条 $progress = round(($bytes_sent / filesize($file_url)) * 100); echo '<script>document.getElementById("progress").innerHTML = "' . $progress . '%";</script>'; // 这里的"progress"是用来显示进度条的HTML元素的ID,可以根据实际情况进行修改 } fclose($handle); exit(); ?> ``` 以上代码通过设置相关的HTTP头字段来实现下载文件,并使用`fread()`函数逐块读取文件内容并发送给浏览器。在每次发送数据块后,通过JavaScript代码动态更新进度条显示。请根据实际情况修改`$file_url`和`$file_name`变量的值,并将适当的HTML进度条元素ID替换为你自己的进度条元素ID。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值