PrevNextUpHome SophiaFramework UNIVERSE 5.3

16.2. HTTP Connection

16.2.1. HTTP Connection Class

The HTTP client can be implemented by taking the following procedures with the SFXHTTPConnection class.

  1. Create the SFXHTTPConnection instance, that is, the HTTP connection.
  2. Open the HTTP connection using the SFXHTTPConnection::Open function.
  3. Set the HTTP request method(default: GET method) using the SFXHTTPConnection::SetMethod function. And set data to the HTTP request body through the output stream obtained by the SFXHTTPConnection::GetStreamWriter function. Set the HTTP request header using the SFXHTTPConnection::SetRequestHeader function, if necessary. (* The HTTP request body can be set using the SFXHTTPConnection::SetRequestContent function.)
  4. In case of the HTTPS connection, set the trust mode(default: SSL_TRUST_MODE_FAIL) using the SFXHTTPConnection::SetTrustMode function.
  5. Connect to the Web server using the SFXHTTPConnection::Connect function, in which set the URL to be connected to and register the callback function notified of the result of HTTP connection request.
  6. The callback function above will be called after notified of the result of connecting to the Web server. (* The execution result(error code) of connecting to the Web server will be passed to the callback function through the 1st argument. If the error code is "SFERR_NO_ERROR", connecting to the Web server is succeeded and the HTTP response is obtained.)
  7. After checking the value of HTTP status code using the SFXHTTPConnection::GetResultCode function, read the HTTP response body through the input stream obtained by the SFXHTTPConnection::GetStreamReader function. The HTTP response header can be gotten using the SFXHTTPConnection::GetResponseHeader function. (* The HTTP response body can be gotten using the SFXHTTPConnection::GetResponseContent function.)
  8. Repeat the above steps from 2. to 7. until no other data needs to be written or read.
  9. Finally, close HTTP connection using the SFXHTTPConnection::Close function.
[Caution] Setting of the MIF file

To use the SFXHTTPConnection class, the web access or network privilege option must be turned on in the MIF file's setting.

[Caution] Limitation on the HTTP communication in BREW 2.0 / 2.1

In case of the HTTP communication in BREW 2.0 / 2.1, data that is greater than or equals 1536 / 65536 bytes respectively cannot be sent.

In this case, you have to divide data into several segments and send them or send data using the SFXTCPSocket / SFXSSLSocket class ( BREW API ISocket interface).

16.2.2. Reading Text Data Using the GET Method

The below is the code to read text data from the HTTP response body obtained using the GET method and display them on BREW Output Window.

Example 16.5. Reading text data using the GET method

// The _http variable is defined as class member variable since used in the callback function
class MyClass {
private:
    SFXHTTPConnection         _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString             _string;
public:
    Void Start(Void);
    Void SaveToFile(SFXPathConstRef path, SFXAnsiStringConstRef string);
    XALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    XALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // HTTP connection using GET method
    // * there is no need to specify "GET" in calling the SFXHTTPConnection::SetMethod function

    // open the HTTP connection
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // start to connect
#if 1
        // in case of HTTP connection
        // connect to the Web server
        // * the connection result will be notified to the OnConnect function
        if ((error = _http.Connect("http://www.example.com/", XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#else
        // in case of HTTPS connection
        // set trust mode if necessary
        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
        // connect to the Web server
        // * the connection result will be notified to the OnConnect function
        if ((error = _http.Connect("https://www.example.com/", XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#endif
            TRACE(">> connecting...");
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // close the HTTP connection
        _http.Close();
    }
    return;
}

// callback function notified of the connection result
XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE(">> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // check response code
        TRACE(">> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get input stream for reading data from HTTP response body
            if ((error = _http.GetStreamReader(1024, &_reader)) == SFERR_NO_ERROR) {

                // perform fetch: read next data from HTTP response body into input stream buffer
                // * the fetch result will be notified to the OnFetch function
                if ((error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch))) == SFERR_NO_ERROR) {

                    TRACE(">> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // close the HTTP connection
       _http.Close();
    }
    return;
}

// callback function notified of the fetch result
XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE(">> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // read data from input stream buffer to the string variable
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // add the string variable to the _string variable
            if ((error = _string.Add(string)) == SFERR_NO_ERROR) {

                // check whether or not data is still remaining
                if (_reader.Ends()) {

                    // since all data have been read, display them on BREW Output Window
                    TRACE("--------");
                    TRACE("%s", _string.GetCString()); // *
                    TRACE("--------");

                    // release resource explicitly
                    // release input stream for reading data from HTTP response body
                    _reader.Release();
                    // close the HTTP connection
                    _http.Close();
                }
                else {

                    // perform fetch: read next data from HTTP response body into input stream buffer
                    // * the fetch result will be notified to the OnFetch function
                    error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch));
                }
            }
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // release input stream for reading data from HTTP response body
        _reader.Release();
        // close the HTTP connection
        _http.Close();
    }
    return;
}

To save the data in the file, call the following function at the "*" position of above code.

Example 16.6. Save the read data in the file

// save string in file (path : file path)
Void MyClass::SaveToFile(SFXPathConstRef path, SFXAnsiStringConstRef string)
{
    SFCError error;

    SFXFile file;                     // file to save data
    SFXAnsiStringStreamWriter writer; // output stream for writing data into file

    // open the file in the read and write mode
    if ((error = file.OpenReadWrite(path)) == SFERR_NO_ERROR) {

        // get output stream for writing data into file
        if ((error = file.GetStreamWriter(string.GetLength(), &writer)) == SFERR_NO_ERROR) {

            // write data from the string variable into output stream buffer
            writer.WriteSFXAnsiString(string);

            // perform flush: write data from output stream buffer into file actually
            // * data will not be written into file unless Flush function is called explicitly
            error = writer.Flush();

            // release output stream for writing data into file
            writer.Release();
        }

        // close the file
        file.Close();
    }
    if (error != SFERR_NO_ERROR) {

        // error handling
    }
    return;
}
[Caution] SFXHTTPConnection Instance

If the SFXHTTPConnection instance is released before the callback function is called, program will not work correctly.

16.2.3. Reading Text Data Using the POST Method

The below is the code to read text data from the HTTP response body obtained using the POST method and display them on BREW Output Window.

Example 16.7. Reading text data using the POST method

// SFXHTTPConnection instance is defined as class member variable for the callback function
class MyClass {
private:
    SFXHTTPConnection         _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString             _string;
public:
    Void Start(Void);
    XALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    XALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFXAnsiStringStreamWriter writer;
    SFXAnsiString             message;
    SFCError error(SFERR_NO_ERROR);

    unused(environment);

    // HTTP connection using POST method
    // * it is necessary to specify "POST" in calling the SFXHTTPConnection::SetMethod function

    // open the HTTP connection
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // message: content of HTTP request body to set
        message = "abcdefghijklmnopqrstuvwxyz";

        // get output stream for writing data into HTTP request body
        // * the stream buffer is variable since the size argument is not specified
        if ((error = _http.GetStreamWriter(&writer)) == SFERR_NO_ERROR) {

            // write data from the message variable into output stream buffer
            // *1. the stream buffer will be expanded automatically depending on the size of data to write
            // *2. the write operation will finish by calling the WriteSFXAnsiString function once
            if ((error = writer.WriteSFXAnsiString(message)) == SFERR_NO_ERROR) {

                // perform flush: write data from output stream buffer into http request body actually
                // * data will not be written into http request body if Flush function is not called explicitly
                if ((error = writer.Flush()) == SFERR_NO_ERROR) {

                    // set request method to POST
                    if ((error = _http.SetMethod("POST")) == SFERR_NO_ERROR) {

                        // start to connect
#if 1
                        // in case of HTTP connection
                        // connect to the Web server
                        // * the connection result will be notified to the OnConnect function
                        if ((error = _http.Connect("http://www.example.com",
                            XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#else
                        // in case of HTTPS connection
                        // set trust mode if necessary
                        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                        // connect to the Web server
                        // * the connection result will be notified to the OnConnect function
                        if ((error = _http.Connect("https://www.example.com",
                            XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#endif
                            TRACE(">> connecting...");
                        }
                    }
                }
            }
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // close the HTTP connection
        _http.Close();
    }
    return;
}

// callback function notified of the connection result
XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE(">> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // examine response code
        TRACE(">> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get input stream for reading data from HTTP response body
            if ((error = _http.GetStreamReader(1024, &_reader)) == SFERR_NO_ERROR) {

                // perform fetch: read data from HTTP request body into input stream buffer
                // * the fetch result will be notified to the OnFetch function
                if ((error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch))) == SFERR_NO_ERROR) {

                    TRACE(">> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }
    if (error != SFERR_NO_ERROR) {
        // if an error occurs
        // close the HTTP connection
        _http.Close();
    }
    return;
}

// callback function notified of the fetch result
XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // read data from input stream buffer into the string variable
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // add the string variable to the _string variable
            if ((error = _string.Add(string)) == SFERR_NO_ERROR) {

                // check whether or not data is still remaining
                if (_reader.Ends()) {

                    // since all data have been read, display them on BREW Output Window
                    TRACE("--------");
                    TRACE("%s", _string.GetCString());
                    TRACE("--------");

                    // release resources explicitly
                    // release input stream for reading data from HTTP response body
                    _reader.Release();
                    // close the HTTP connection
                    _http.Close();
                }
                else {

                    // perform fetch: read data from HTTP response body into input stream buffer
                    // * the fetch result will be notified to the OnFetch function
                    error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch));
                }
            }
        }
    }
    if (error != SFERR_NO_ERROR) {
        // if an error occurs
        // release input stream for reading data from HTTP response body
        _reader.Release();
        // close the HTTP connection
        _http.Close();
    }
    return;
}

16.2.4. Reading the Binary Data from the HTTP Response Body

The below is the code to read the binary data from the HTTP response body and save them into the file as it they are.

Example 16.8. Reading the binary data from the HTTP response body

// The _http variable is defined as class member variable since used in the callback function
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXFile _file;
    SFXBinaryStreamReader _reader; // input stream for reading data from HTTP response body
    SFXBinaryStreamWriter _writer; // output stream for writing data into file 
    SFXBuffer _buffer;     // variable for storing read data
    SFXBuffer _tempbuffer; // variable for storing read data temporarily
    UInt32    _bufferSize; // buffer size of output stream for writing data in file
public:
    Void Start(Void);
    XALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    XALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // HTTP connection using GET method
    // * there is no need to specify "GET" in calling the SFXHTTPConnection::SetMethod function

    // open the HTTP connection
    if ((error = _http.Open()) == SFERR_NO_ERROR) {
				
if 1
        // in case of HTTP connection
        // connect to the Web server
        // * the connection result will be notified to the OnConnect function
        if ((error = _http.Connect("http://www.example.com", XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#else
        // in case of HTTPS connection
        // set trust mode if necessary
        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
        // connect to the Web server
        // * the connection result will be notified to the OnConnect function
        if ((error = _http.Connect("https://www.example.com", XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#endif
            TRACE(">> connecting...");
        }
        if (error != SFERR_NO_ERROR) {

            // if an error occurs

            // close the HTTP connection
            _http.Close();
        }
    }
    return;
}

// callback function notified of the connection result
XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE(">> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // check response code
        TRACE(">> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get input stream for reading data from HTTP response body
            if ((error = _http.GetStreamReader(_bufferSize, &_reader)) == SFERR_NO_ERROR) {

                // perform fetch: read data from HTTP response body into input stream buffer
                // * the fetch result will be notified to the OnFetch function
                if ((error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch))) == SFERR_NO_ERROR) {

                    TRACE(">> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }
    // prepare to write data from HTTP response body to file
    if (error == SFERR_NO_ERROR) {

        // set buffer size
        _bufferSize = 1024;

        // set the size of _tempbuffer to 1024
        if ((error = _tempbuffer.SetSize(_bufferSize)) == SFERR_NO_ERROR) {

            // open file in read/write mode
            if ((error = _file.OpenReadWrite(SFXPath("/example.dat"))) == SFERR_NO_ERROR) {

                // get output stream for writing data into file
                error = _file.GetStreamWriter(_bufferSize, &_writer);
            }
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs

        // release input stream for reading data from HTTP response body
        _reader.Release();
        // close the HTTP connection
        _http.Close();
        // release output stream for writing data into file
        _writer.Release();
        // close the file
        _file.Close();
    }
    return;
}

// callback function notified of the fetch result
XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    TRACE(">> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // set the size of _tempbuffer to readable size
        _tempbuffer.SetSize(_reader.GetReadableSize());

        // read data from input stream buffer into the _tempbuffer variable
        if ((error = _reader.Read(&_tempbuffer)) == SFERR_NO_ERROR) {

            // write data from the _tempbuffer variable into output stream buffer
            if ((error = _writer.Write(_tempbuffer)) == SFERR_NO_ERROR) {

                // perform flush: write data from output stream buffer into file actually
                // * data will not be written into file if Flush function is not called explicitly

                if ((error = _writer.Flush()) == SFERR_NO_ERROR) {

                    // add the _tempbuffer variable to the _buffer variable
                    if ((error = _buffer.Add(_tempbuffer)) == SFERR_NO_ERROR) {

                        // check whether or not data is still remaining
                        if (_reader.Ends()) {

                            // since all data have been read, display them on BREW Output Window
                            TRACE("--------");
                            TRACE("%s", _buffer.GetBuffer());
                            TRACE("--------");

                            // release resources explicitly
                            // release input stream for reading data from HTTP response body
                            _reader.Release();
                            // close the HTTP connection
                            _http.Close();
                            // release output stream for writing data into file
                            _writer.Release();
                            // close the file
                            _file.Close();
                        }
                        else {

                           // perform fetch: read next data from HTTP response body into input stream buffer
                           // * the fetch result will be notified to the OnFetch function
                           error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch));
                        }
                    }
                }
            }
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // release input stream for reading data from HTTP response body
        _reader.Release();
        // close the HTTP connection
        _http.Close();
        // release output stream for writing data into file
        _writer.Release();
        // close the file
        _file.Close();
    }
    return;
}

16.2.5. Uploading the File through the HTTP Communication

The below is the code to upload the file data to the Web server.

In the method to use the SetRequestContentToFileData function, data will be uploaded using the HTTP communication after all data is read into heap as the HTTP request body from the file. Therefore, the file size that can be uploaded is limited to the mobile phone's memory size.

In the method to use the SetRequestContentToFileStorage function, the file storage will be set as the HTTP request body using the SFXHTTPConnection::SetRequestContent function. In this method, since file data will be sent by streaming, the file size that can be uploaded does not depend on the mobile phone's memory size.

[Note] Note

The SFXHTTPConnection::SetRequestContent function is effective in SophiaFramework UNIVERSE 5.1.11 or above.

[Caution] Caution

In case of the HTTP communication in BREW 2.0 / 2.1, due to the BREW bug, the file whose size is greater than or equals 1536 / 65536 bytes respectively cannot be uploaded.

In this case, you have to divide the file into several segments and upload them or upload the file using the SFXTCPSocket / SFXSSLSocket class ( BREW API ISocket interface).

Example 16.9. Upload the file through the HTTP communication

#define SOURCE_FILE_PATH  "/data.txt"  // file to upload

// The _http variable is defined as class member variable since used in the callback function
class MyClass {
private:
    SFXHTTPConnection         _http;     // HTTP connection
    SFXAnsiStringStreamReader _reader;   // input stream for reading data from HTTP response body
    SFXAnsiString             _string;   // content of the read HTTP response body
public:
    SFCError Start(Void);
    SFCError SetRequestContentToFileData(SFXFileRef file);
    SFCError SetRequestContentToFileStorage(SFXFileRef file);
    XALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    XALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

SFCError MyClass::Start(Void)
{
    SFXFile file;
    SFCError error(SFERR_NO_ERROR);

    // open the HTTP connection
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // open the file
        if ((error = file.OpenReadOnly(SFXPath(SOURCE_FILE_PATH))) == SFERR_NO_ERROR) {

#if 1
            if ((error = SetRequestContentToFileData(file)) == SFERR_NO_ERROR) {
#else
            if ((error = SetRequestContentToFileStorage(file)) == SFERR_NO_ERROR) {
#endif
                // close the file
                file.Close();

                if (error == SFERR_NO_ERROR) { 

                    // if succeeds to set the HTTP request body:

                    // set request method to POST
                    // * in case of the POST method, not only text but binary can be sent
                    if ((error = _http.SetMethod("POST")) == SFERR_NO_ERROR) {

                        // start to connect
#if 1
                        // in case of HTTP connection
                        // connect to the Web server
                        // * the connection result will be notified to the OnConnect function
                        if ((error = _http.Connect("http://www.example.com", XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#else
                        // in case of HTTPS connection
                        // set trust mode if necessary
                        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                        // connect to the Web server
                        // * the connection result will be notified to the OnConnect function
                        if ((error = _http.Connect("https://www.example.com", XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {
#endif
                            TRACE(">> connecting...");
                        }
                    }
                }
            }
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // close the file
        file.Close();
        // close the HTTP connection
        _http.Close();
    }
    return error;
}

// method to set the HTTP request body after the content of the HTTP request body is made on heap
SFCError MyClass::SetRequestContentToFileData(SFXFileRef file)
{
    SFXBinaryStreamReader   reader; // input stream for reading data from file
    SFXBinaryStreamWriter   writer; // out stream for writing data into HTTP request body
    SFXBuffer               buffer; // buffer to store data read from file
    SFCError error(SFERR_NO_ERROR); // error value

    // get out stream for writing data into HTTP request body
    if ((error = _http.GetStreamWriter(1024, &writer)) == SFERR_NO_ERROR) {

        // get input stream for reading data from file
        if ((error = file.GetStreamReader(1024, &reader)) == SFERR_NO_ERROR) {

            // copy data from file to HTTP request body
            while ((error == SFERR_NO_ERROR) && !reader.Ends()) {

                // * repeat the following processing until the end of the file is reached

                // perform fetch: read data from file into input stream buffer
                if ((error = reader.Fetch()) == SFERR_NO_ERROR) {
                        
                    // set the size of buffer to readable size
                    if ((error = buffer.SetSize(reader.GetReadableSize())) == SFERR_NO_ERROR) {

                        // read data from input stream buffer into the buffer variable
                        if ((error = reader.Read(&buffer)) == SFERR_NO_ERROR) {
                                    
                            // write data from the buffer variable into output stream buffer
                            if ((error = writer.Write(buffer)) == SFERR_NO_ERROR) {

                                // perform flush: write data from output stream buffer into HTTP request body actually
                                // * data will not be written into HTTP request body if Flush function is not called explicitly
                                error = writer.Flush();
                            }
                        }
                    }
                }
            }
        }
    }
    // release input stream for reading data from file
    reader.Release();
    // release out stream for writing data into HTTP request body
    writer.Release();
    return error;
}

// method to set the HTTP request body to the file storage
SFCError MyClass::SetRequestContentToFileStorage(SFXFileRef file)
{
    UInt32 size;
    SFCError error(SFERR_NO_ERROR);

    // get the file size
    if ((error = SFXFile::GetSize(SFXPath(SOURCE_FILE_PATH), &size)) == SFERR_NO_ERROR) {

        // set the HTTP request body to the file storage and its size
        error = _http.SetRequestContent(file, size);
    }

    // you can describe as the below without the size argument instead of the above code
    // * in this case, the file size is automatically set as the size of the HTTP request body
    // error = _http.SetRequestContent(file);

    return error;
}


// callback function notified of the connection result
XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE(">> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // check response code
        TRACE(">> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get input stream for reading data from HTTP response body
            if ((error = _http.GetStreamReader(1024, &_reader)) == SFERR_NO_ERROR) {

               // perform fetch: read data from HTTP response body into input stream buffer
               // * the fetch result will be notified to the OnFetch function
               if ((error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch))) == SFERR_NO_ERROR) {

                    TRACE(">> fetching...");
                }
            }
        }
        else {

            error = SFERR_INVALID_STATE;
        }
    }
    if (error != SFERR_NO_ERROR) {

        // If an error occurs
        // input stream for reading data from HTTP response body
        _reader.Release();
        // close the HTTP connection
        _http.Close();
    }
    return;
}

// callback function notified of the fetch result
XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE(">> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // read data from input stream buffer into the string variable
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // add the string variable to the _string variable
            if ((error = _string.Add(string)) == SFERR_NO_ERROR) {

                // check whether or not data is still remaining
                if (_reader.Ends()) {

                    // since all data have been read, display them on BREW Output Window
                    TRACE("--------");
                    TRACE("%s", _string.GetCString());
                    TRACE("--------");

                    // release resource explicitly
                    _reader.Release();
                    _http.Close();
                }
                else {

                    // read next data from HTTP response body into input stream buffer
                    // the fetch result will be notified to the OnFetch function
                    error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch));
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // release input stream for reading data from HTTP response body
        _reader.Release();
        // close the HTTP connection
        _http.Close();
    }
    return;
}

The SetRequestContentToFileData function can be implemented using the memory storage(SFXMemory) and the SFXHTTPConnection::SetRequestContent function as follows:

Example 16.10. Another implementation of the SetRequestContentToFileData function

class MyClass {
private:
    ...
    SFXMemory _memory;  // memory storage
    ...
public:
    ....
};

SFCError MyClass::Start(Void)
{
    ...

    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // close the memory
        _memory.Close();
        // close the file
        file.Close();
        // close the HTTP connection
        _http.Close();
    }
    return error;
}

// method to set the HTTP request body using the memory storage
SFCError MyClass::SetRequestContentToFileData(SFXFileRef file)
{
    SFXBinaryStreamReader   reader; // input stream for reading data from file
    SFXBinaryStreamWriter   writer; // out stream for writing data into memory
    SFXBuffer               buffer; // buffer to store data read from file
    SFCError error(SFERR_NO_ERROR); // error value

    // open the memory
    if ((error = _memory.Open()) == SFERR_NO_ERROR) {

        // get out stream for writing data into memory
        if ((error = _memory.GetStreamWriter(1024, &writer)) == SFERR_NO_ERROR) {

            // get input stream for reading data from file
            if ((error = file.GetStreamReader(1024, &reader)) == SFERR_NO_ERROR) {

                // copy data from file into memory
                while ((error == SFERR_NO_ERROR) && !reader.Ends()) {

                    // * repeat the following processing until the end of the file is reached

                    // perform fetch: read data from file into input stream buffer
                    if ((error = reader.Fetch()) == SFERR_NO_ERROR) {
                        
                        // set the size of buffer to readable size
                        if ((error = buffer.SetSize(reader.GetReadableSize())) == SFERR_NO_ERROR) {

                            // read data from input stream buffer into the buffer variable
                            if ((error = reader.Read(&buffer)) == SFERR_NO_ERROR) {
                                    
                                // write data from the buffer variable into output stream buffer
                                if ((error = writer.Write(buffer)) == SFERR_NO_ERROR) {

                                // perform flush: write data from output stream buffer into memory
                                // * data will not be written into HTTP request body if Flush function is not called explicitly
                                error = writer.Flush();
                            }
                        }
                    }
                }
            }
        }
    }
    if (error == SFERR_NO_ERROR) {

        // set the HTTP request content to the memory and its size
        error = _http.SetRequestContent(_memory, _memory.GetSize());
        // * the above can be described as "error = _http.SetRequestContent(_memory);"
    }
    // release input stream for reading data from file
    reader.Release();
    // release out stream for writing data into memory
    writer.Release();
    return error;
}

// callback function notified of the connection result
XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE(">> connected... : %d", error);

    // close the memory
    _memory.Close();

    if (error == SFERR_NO_ERROR) {

         ...

}

The below is the code to divide the file data into several segments and upload them to the Web server repeatedly.

Example 16.11. Upload the divided file segments through the HTTP communication

#define SOURCE_FILE_PATH  "/data.txt"  // file to upload
#define SEGMENT_SIZE      1535         // segment size

// The _http variable is defined as class member variable since used in the callback function
class MyClass {
private:
    SFXHTTPConnection         _http;     // HTTP connection
    SFXAnsiStringStreamReader _reader;   // input stream for reading data from HTTP response body
    SFXAnsiString             _string;   // content of the read HTTP response body
    SFXFile                   _file;     // file
    UInt32                    _fileSize; // file size
    UInt32                    _sentSize; // size of the sent data
public:
    SFCError Start(Void);
    SFCError UploadFileSegment(Void);
    SFCError SetFileSegment(SFXFileRef file);
    XALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    XALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

SFCError MyClass::Start(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // open the HTTP connection
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // open the file
        if ((error = _file.OpenReadOnly(SFXPath(SOURCE_FILE_PATH))) == SFERR_NO_ERROR) {

            // get the file size
            if ((error = SFXFile::GetSize(SFXPath(SOURCE_FILE_PATH), &_fileSize)) == SFERR_NO_ERROR) {

                // set request method to POST
                // * in case of the POST method, not only text but binary can be sent
                if ((error = _http.SetMethod("POST")) == SFERR_NO_ERROR) {

                    // upload the first segment
                    error = UploadFileSegment();
                }
            }
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // close the file
        _file.Close();
        // close the HTTP connection
        _http.Close();
    }
    return error;
}

// upload the file segment
SFCError MyClass::UploadFileSegment(Void)
{
    SFCError error;

    // set the file segment
    if ((error = SetFileSegment(_file)) == SFERR_NO_ERROR) {

        // connect to the Web server
        // * the connection result will be notified to the OnConnect function
        if ((error = _http.Connect("http://www.example.com/cgi-bin/fileupload.cgi", XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) {

            TRACE(">> connecting...");
        }
    }
    return error;
}

// set the file segment
SFCError MyClass::SetFileSegment(SFXFileRef file)
{
    UInt32                    diff; // size of the remaining data:  when it is less than or equals
    SFCError error(SFERR_NO_ERROR); // error value

    if (_sentSize + SEGMENT_SIZE < _fileSize) {

        _sentSize += SEGMENT_SIZE;

        //  set the HTTP request body to the SEGMENT_SIZE of data from the current file pointer
        error = _http.SetRequestContent(file, SEGMENT_SIZE);
    }
    else {

        if (_fileSize > _sentSize) {

            diff = _fileSize - _sentSize;
            _sentSize = _fileSize;

        //  set the HTTP request body to the diff size of data from the current file pointer
            error = _http.SetRequestContent(file, diff);
        }
        else {

            error = SFERR_FAILED;
        }
    }
    return error;
}

// callback function notified of the connection result
XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE(">> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // check response code
        TRACE(">> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get input stream for reading data from HTTP response body
            if ((error = _http.GetStreamReader(1024, &_reader)) == SFERR_NO_ERROR) {

               // perform fetch: read data from HTTP response body into input stream buffer
               // * the fetch result will be notified to the OnFetch function
               if ((error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch))) == SFERR_NO_ERROR) {

                    TRACE(">> fetching...");
                }
            }
        }
        else {

            error = SFERR_INVALID_STATE;
        }
    }
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // input stream for reading data from HTTP response body
        _reader.Release();
        // close the file
        _file.Close();
        // close the HTTP connection
        _http.Close();
    }
    return;
}

// callback function notified of the fetch result
XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE(">> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // read data from input stream buffer into the string variable
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // add the string variable to the _string variable
            if ((error = _string.Add(string)) == SFERR_NO_ERROR) {

                // check whether or not data is still remaining
                if (_reader.Ends()) {

                    // since all data have been read, display them on BREW Output Window
                    TRACE("--------");
                    TRACE("%s", _string.GetCString());
                    TRACE("--------");

                    // release resource explicitly
                    _reader.Release();

                    if (_sentSize == _fileSize) {

                        // when all file segments have been uploaded:

                        // close the file
                        _file.Close();
                        // close the HTTP connection
                        _http.Close();
                    } else {

                        // when file segments to upload still exist:

                        // upload the next file segment
                        error = UploadFileSegment();
                    }

                    _http.Close();
                }
                else {

                    // read next data from HTTP response body into input stream buffer
                    // the fetch result will be notified to the OnFetch function
                    error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch));
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {

        // if an error occurs
        // input stream for reading data from HTTP response body
        _reader.Release();
        // close the file
        _file.Close();
        // close the HTTP connection
        _http.Close();
    }
    return;
}