none
如何实现一个文件的下载功能(文件格式可以是多样化的)? RRS feed

全部回复

  • 用SHBrowseForFolder选择路径下载目录,把文件写到目录中。
    或者用OpenFileDialog指定文件下载
    2009年5月13日 4:22
    版主
  • 得看服务器允许什么通讯方式吧
    MSMVP VC++
    2009年5月13日 4:25
    版主
  • 能不能给一些原理性的描述啊?而不是具体的函数实现,我想知道其中的原理知识。谢啦!O(∩_∩)O~
    2009年5月13日 9:26
  • 如果要使用socket做CS结构,通过socket把文件流接受到client,然后在指定目录创建文件把流写进文件。
    2009年5月14日 0:59
    版主
  • CHttpFile
    Hello world
    2009年5月15日 2:38
    版主
  • 请解释一下它的原理吧?O(∩_∩)O~
    2009年5月15日 3:19
  • 请做过这方面的朋友简单说下步骤或者方法就好了。

    具体就是实现,嗯,比如360软件或者瑞星杀毒软件上那种下载,说的再详细一点就是服务器如何放置某文件,然后客户端界面上提供这个文件的下载,然后用户点下鼠标就可以实现下载了,有做过这方面的吗?只要很简单的实现功能就行了,说一下大概的实现步骤就好,谢谢各位了。
    网友回复:HTTP下载

    HINTERNET hSession = InternetOpen.....

    http://topic..net/u/20080828/11/99974020-05e1-4f6a-8c0c-ebfaf0face9b.html


    网友回复:1.客户端发从服务器下载文件列表,并显示给客户
    2.客户点击某个文件,客户端把文件名发送给服务器,接着就建立连接
    3.文件传输
    网友回复:能再仔细一下的说用什么样的方法传输文件吗?SOCKET?还是什么的?

    呵呵,回答完这个问题就结贴。

    只需要用什么方法就好了,比如大概什么类,什么API之类的,我搜索不到了。
    网友回复:mark
    网友回复:最简单就是使用wininet库,服务器只要有WebServer就行。如果是MFC,用CHttpFile吧。
    网友回复:URLDownloadToFile
    HRESULT URLDownloadToFile(
    LPUNKNOWN pCaller,
    LPCSTR szURL,
    LPCSTR szFileName,
    DWORD dwReserved,
    LPBINDSTATUSCALLBACK lpfnCB
    );

    Downloads bits from the Internet and saves them to a file. The client can choose to be notified of progress through a notification callback.

    pCaller
    Address of the controllingIUnknown interface of the calling ActiveX component (if the caller is an ActiveX component). If the calling application is not an ActiveX component, this value can be set to NULL. Otherwise, the caller is a COM object that is contained in another component (such as an ActiveX control within the context of an HTML page). This parameter represents the outermost IUnknown of the calling component. The function attempts the download within the context of the ActiveX client framework and allows the caller's container to receive callbacks on the progress of the download.
    szURL
    String containing the URL to be downloaded. Cannot be NULL.
    szFileName
    String containing the name of the file to create for bits that come from the download.
    dwReserved
    Reserved for future use. Must be zero.
    lpfnCB
    Address of the caller's IBindStatusCallback interface. URLDownloadToFile calls this interface's IBindStatusCallback::OnProgress method on a connection activity, including the arrival of data. IBindStatusCallback::OnDataAvailable is never called. Implementing IBindStatusCallback::OnProgress allows a caller to implement a user interface or other progress monitoring functionality. It also allows the download operation to be canceled by returning E_ABORT from the IBindStatusCallback::OnProgress call. Can be NULL.
    网友回复:AfxInet更简单,和下载网页一样
    网友回复:http or tcp
    实现文件版本检测和文件的发送。
    网友回复:最简单的就是通过Http下载文件,我这给你一个例子函数:

    C/C code

     

     

    Code highlighting produced by Actipro CodeHighlighter (freeware)

    http://www.CodeHighlighter.com/

     

     

    //****************************************************************************************//

    //函数 CDoUpdateDlg::DownFile

    //主要功能:

    //参数列表:

    //         1、CString strUrl:是文件的URL地址

    //         2、strFile:文件名

    //         3、CString strPath:是存放到本地的路径

    //返回值:

    //备注:

    //****************************************************************************************//

    bool DownFile(CString strUrl, CString strFile, CString strPath)

    {

        m_nCurFileSize = 0;

        bool bRet = false;

        CString strSentence;

        CInternetSession sess;//Create session

        CHttpFile* fileGet;

        CException* e;

        TRY

        {

            fileGet=(CHttpFile*)sess.OpenURL(strUrl);//Open file

        }

        CATCH_ALL(e)

        {

            fileGet = 0;

            return false;

        }

        END_CATCH_ALL

     

        DWORD dwStatus;

        DWORD dwBuffLen = sizeof(dwStatus);

     

        if(fileGet)

        {

            BOOL bSuccess = fileGet->QueryInfo(

                HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,

                &dwStatus, &dwBuffLen);

     

            m_nCurFilePos = 0;

            char buffer[1024 * 4   1];

            unsigned long nSize = 1024 * 4;

            int n = 0;

            if( bSuccess && dwStatus >= 200 && dwStatus < 300 )

            {

                fileGet->QueryInfo(HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwBuffLen);

                m_nCurFileSize = dwStatus;

     

                char szFileName[1024];

                GetAppPath(szFileName, 1024);

                strcpy(szFileName, strPath);

                strcat(szFileName, strFile);

                FILE *f;

                f = fopen(szFileName, "wb");

                if(f == NULL)

                {

                    fileGet->Close();

                    delete fileGet;

                    return false;

                }

                if(m_nCurFileSize < nSize)

                    nSize = m_nCurFileSize;

                int nCount = fileGet->Read(buffer, nSize);

                unsigned long nDownLen = 0;

                while(nCount > 0)

                {

                    nDownLen  = nCount;

                    m_nCurFilePos  = nCount;

                    CDC *pDC = GetDC();

                    DrawDownProcess(pDC);

                    ReleaseDC(pDC);

                    fwrite(buffer, sizeof(char), nCount, f);

                    nCount = fileGet->Read(buffer, nSize);

                }

                fclose(f);

                if(m_nCurFileSize > nDownLen)

                    bRet = false;

                else

                    bRet = true;

            }

            fileGet->Close();

            delete fileGet;

        }

        else

        {

            TRACE0("对不起,连接超时,无法打开站点!");

            bRet = false;

        }

        sess.Close();

        return bRet;

    }

     


    网友回复:socket就可以了,tcp或udp协议
    将要下载的文件分组成合适大小传送
    服务器端socket(protocol,..), bind(port,..),[listen(..)],[accept(..)],recv/recvfrom/send/sendto
    客户端socket(protocol,..),[connect(..)],recv/recvfrom/send/sendto

    网友回复:上面的都说得差不多了,我来接分.
    网友回复:我也想接分
    网友回复:http,ftp下载比较常见,你要更牛B的可以是bt或emule等下载.
    网友回复:学习了
    网友回复:可以用winnet的实现


    C/C code

     

     

    Code highlighting produced by Actipro CodeHighlighter (freeware)

    http://www.CodeHighlighter.com/

     

     

     

    int StartDownload(DOWNLOAD_PROPERTY* pDataCon)

    {

        if (NULL == pDataCon || DOWNLOAD_PROPERTY_SIZE != pDataCon->m_dwSize)

        {

            return ERR_INVALID_PARAM;

        }

     

        #define HINET_SERVER_NAME    "www.rootkit.com"

        #define HINET_CACHE_FILE    "object.exe"

        #define DOWNLOAD_REQ_SIZE    4096

       

        const char* szAccept= "*/*";

     

        int nRet = ERR_SUCCESS;

       

        DWORD dwRealRead = 0;

        DWORD dwRealWrite = 0;

        DWORD dwBytesToRead = 0;

        DWORD dwBufLen = sizeof(dwBytesToRead);

     

        CHAR RecvBuf[DOWNLOAD_REQ_SIZE] = {0};   

     

        HINTERNET hSession = NULL;

        HINTERNET hConnect = NULL;

        HINTERNET hRequest = NULL;

     

        HANDLE hFile = INVALID_HANDLE_VALUE;

        hFile = CreateFile(HINET_CACHE_FILE,

                            GENERIC_READ | GENERIC_WRITE,

                            FILE_SHARE_READ | FILE_SHARE_WRITE,

                            NULL,

                            CREATE_ALWAYS,

                            FILE_ATTRIBUTE_NORMAL,

                            NULL);

        if (INVALID_HANDLE_VALUE == hFile)

        {       

            nRet = ERR_CREATE_FILE;

            goto _Cleanup;

        }

     

        hSession = InternetOpen("HTTP",

                                INTERNET_OPEN_TYPE_PRECONFIG,

                                NULL,

                                NULL,

                                0);

        if (NULL == hSession)

        {

            nRet = ERR_INTERNET_OPEN;

            goto _Cleanup;

        }

     

        hConnect = InternetConnect(hSession,

                                    HINET_SERVER_NAME,

                                    INTERNET_DEFAULT_HTTP_PORT,

                                    NULL,

                                    NULL,

                                    INTERNET_SERVICE_HTTP,

                                    0,

                                    0);

        if (NULL == hConnect)

        {

            nRet = ERR_INTERNET_CONNECT;

            goto _Cleanup;

        }

     

        hRequest = HttpOpenRequest(hConnect,

                                    "GET",

                                    "/MD5CHECK.exe",

                                    "HTTP/1.1",

                                    NULL,

                                    &szAccept,

                                    INTERNET_FLAG_RELOAD,

                                    0);

        if (NULL == hRequest)

        {

            nRet = ERR_INTERNET_REQ;

            goto _Cleanup;

        }

     

        if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))

        {

            DWORD dwErr = GetLastError();

            nRet = ERR_INTERNET_SENDREQ;

            goto _Cleanup;

        }

     

        if (!HttpQueryInfo(hRequest,

                            HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,

                            (LPVOID)&dwBytesToRead,

                            &dwBufLen,

                            NULL))

        {

            nRet = ERR_INTERNET_QUERY;

            goto _Cleanup;

        }

     

        while (InternetReadFile(hRequest, RecvBuf, DOWNLOAD_REQ_SIZE, &dwRealRead))

        {

            if (0 == dwRealRead)

            {           

                break;

            }       

           

            WriteFile(hFile, RecvBuf, DOWNLOAD_REQ_SIZE, &dwRealWrite, NULL);

            Sleep(0);

        }

       

        if (INVALID_HANDLE_VALUE != hFile)

        {

            CloseHandle(hFile);

            hFile = INVALID_HANDLE_VALUE;

        }

     

    _Cleanup:

     

        if (INVALID_HANDLE_VALUE != hFile)

        {

            CloseHandle(hFile);

            hFile = INVALID_HANDLE_VALUE;

        }

     

        if (NULL != hSession)

        {

            InternetCloseHandle(hSession);

            hSession = NULL;

        }

       

        if (NULL != hConnect)

        {

            InternetCloseHandle(hConnect);

            hConnect = NULL;

        }

       

        if (NULL != hRequest)

        {

            InternetCloseHandle(hRequest);

            hRequest = NULL;

        }

     

        if (nRet != ERR_SUCCESS)

        {

            if (0 == _access(HINET_CACHE_FILE, 0))

            {

                DeleteFile(HINET_CACHE_FILE);

            }       

        }

       

        return nRet;

    }

     


    Computing enthusiasts!
    2009年5月17日 7:23
  • 用HTTP系统API在Wininet.h里有  
      HttpAddRequestHeaders,   HttpQueryInfo,   HttpSendRequest,   InternetCloseHandle,   InternetConnect,   InternetOpen,   InternetReadFile,   HttpOpenRequest
    Computing enthusiasts!
    2009年5月17日 7:24
  • 简单的来说发送文件就和普通的发送数据没什么区别,
    若是TCP不用考虑组包的问题,首先用ReadFile读出文件的一部分再放到缓冲里,然后用Send把这部分发送过去,然后再读一部分再发送过去,直到这个文件全部发送完毕.接收段只要收到数据就写到磁盘里就可以了。
    要是UDP的话就复杂一些了,因为它不能保证包的先后顺序。还要在包上加个序号或是其他的什么能保证还原顺序的东西。
    Hello world
    2009年5月17日 15:28
    版主