2007-04-29

随缘

《太极张三丰》片尾曲

制作:音乐工厂
编曲:花比傲
作曲:罗大佑
作词:林夕

刀光剑影不是我门派
天空海阔自有我风采
双手一推非黑也非白
不好也不坏
没有胜又何来败

没有去哪有来
手中无剑心中无尘
才是我胸怀
随缘而去乘风而来
才是我胸怀

唇枪舌剑不合我姿态
天空海阔才是我风采
双手一推非虚也非实
不慢也不快
没有胜又何来败

没有动哪有静
手中无剑心中无尘
才是我胸怀
随缘而去乘风而来
才是我胸怀

2007-04-02

使用 Wininet 以 PUT 方法上传文件

客户端与 HTTP 服务器通常使用 GET 和 POST 方法进行交互,其中, GET 方法是客户端从服务器取得文件, POST 方法是客户端提交数据给服务器。
当我们需要上传文件给服务器的时候,可以使用 POST 和 PUT 方法。 POST 方法通常用来向表单提交数据,此时表单的 enctype 属性被设置为默认值"application/x-www-form-urlencoded" ,当需要向服务器提交大量文本、二进制数据时, enctype 属性将被设置为"multipart/form-data" 。 POST方法的优势在于能够在一次提交过程中传输多条数据和多个文件,但是实现起来比较复杂,如果我们只是需要传输一个文件的时候,使用 PUT 方法就方便多了。
PUT 方法的实现很简单,只需要打开 HTTP 连接,发送文件大小,读取本地文件,将内容以二进制方式写入到 HTTP 消息体中, MFC 代码如下:
  CInternetSession session;
  CHttpConnection * pHttpConn = NULL;
  CHttpFile * pHttpFile = NULL;
  try
  {
    pHttpConn =session.GetHttpConnection(m_serverHost, m_serverPort);

    //接收所有文件类型
    TCHAR accept[] = _T("*/*");
    //参数需要的数组
    const TCHAR *acArray[2] = {accept,NULL};
    LPCTSTR* ppstrAcceptTypes = acArray;

    //打开PUT方法的HTTP连接
    pHttpFile =pHttpConn->OpenRequest("PUT", m_serverObjectName, NULL, 1, ppstrAcceptTypes);

    //发送提交文件的大小,m_pLocalFile为文件对象指针
    DWORD fileLength =m_pLocalFile->GetLength();
    pHttpFile->SendRequestEx(fileLength);

    BYTE buffer[HTTP_BUFFER];
    //写入文件内容
    m_pLocalFile->SeekToBegin();       
    int nRead = m_pLocalFile->Read(buffer,HTTP_BUFFER);
    while (nRead==HTTP_BUFFER)
    {
      pHttpFile->Write(buffer, nRead);
      nRead =m_pLocalFile->Read(buffer, HTTP_BUFFER);
    }
    pHttpFile->Write(buffer, nRead);
    pHttpFile->EndRequest();

    //如果需要读取返回的结果,在这里调用 CHttpFile::Read 函数

    //释放资源
    pHttpFile->Close();
    pHttpConn->Close();
  }
  catch (CInternetException * pEx)
  {
    pEx->Delete();
    if (pHttpFile!=NULL)
    {
      pHttpFile->Close();
    }
    if (pHttpConn!=NULL)
    {
      pHttpConn->Close();
    }
  }
在上面的代码中,我们将本地文件上传到服务器中,由于 PUT 方法的消息体只能传送文件内容,所以,如果需要传输附加的参数,可以调用 CHttpFile::AddRequestHeaders 函数,具体使用方法请参考 MSDN 。
在 WEB 应用程序中,如果服务器端使用 ASP.NET ,可以通过 HttpRequest.InputStream 属性得到 Stream对象,从中读出二进制数据;如果服务器端使用 Java Servlet ,可以通过 HttpServletRequest.getInputStream 方法得到 ServletInputStream 对象,从中读出二进制数据。