Upload File to a Server using HTTP possible?

Login to reply to this topic.
Tue, 2005-02-08 16:58
Joined: 2005-02-08
Forum posts: 4
Hi guys,

I will like to ask if it is possible to upload a file from the mobile device to a server (assuming I'm using a servlet to receive incoming file) using HTTP?

Is it possible to provide me with a little sample code, as I'm very new to the Symbian world. I tried searching the API documentation, but I cannot find any section about HTTP at all. I don't know why, because I was told that a library existed. I'm using the Series 60 2.0 SDK, by the way.

Thank you very much for your attention.

Tue, 2005-02-08 17:08
Joined: 2005-02-02
Forum posts: 18
Upload File to a Server using HTTP possible?
study the echoclient example in Series60_v20_CW\Examples\networking\tcpip\echoclientengine
Wed, 2005-02-16 11:40
Joined: 2005-01-13
Forum posts: 31
Upload File to a Server using HTTP possible?
Start looking at the MHTTPDataSupplier and MHTTPTransactionCallback interfaces, in you class you have to overload these methods and cause they are virtual you have to implement some code in them:
Code:
public: // from MHTTPDataSupplier
// methods inherited from MHTTPDataSupplier
virtual TBool GetNextDataPart(TPtrC8& aDataPart);
virtual void ReleaseData();
virtual TInt OverallDataSize();
virtual TInt Reset();

// methods from MHTTPTransactionCallback
virtual void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
virtual TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
Here is how I did with some of the more simple ones. GetNextDataPart() should return EFalse if there is more bytes in the buffer and when it's done ETrue.
Code:
TBool CMECKMAppUi::GetNextDataPart(TPtrC8& aDataPart)
{
TBool retVal = EFalse;
aDataPart.Set(iReqBodySubmitBufferPtr);
retVal = (iReqBodySubmitBufferPtr.Length() == 0);
return retVal;
}

void CMECKMAppUi::ReleaseData()
{
TPtr8 buff = iOriginalBuffer->Des();
buff.Zero();
}

TInt CMECKMAppUi::OverallDataSize()
{
return iHTTPBodySize;
}

TInt CMECKMAppUi::Reset()
{
return KErrNotSupported;
}
TInt CMECKMAppUi::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, const THTTPEvent& /*aEvent*/)
{
return aError;
}
The more difficult one is the MHFRunL which in case of submission errors is invoked and in my case it handles KErrCancel (User cancel) and some other error within HTTP. EGotResponseHeaders is invoked when you get an answer, then you can check header etc. EGotResponseBodyData is called next time if the response has a body (e.g. HTML-code and text)
So when you get a response MHFRunL is called once for headers, and once more shortly after for the body. Notice how RHTTPResponse::Body() has the same methods that you've earlier overloaded?(e.g. GetNextDataPart(), ReleaseData(), OverallDataSize(), Reset()). You use them to get the response.
Code:
void CMECKMAppUi::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
{
switch (aEvent.iStatus)
{
case KErrCancel:
{
// User cancelled dialog DISP error dialog R_BACKUP_CANCELLED_MSG_8
ibolHTTPSend = KErrCancel;
}break;
case THTTPEvent::EGotResponseHeaders:
{
// HTTP response headers have been received. We can determine now if there is
// going to be a response body to save.
RHTTPResponse resp = aTransaction.Response();
TInt status = resp.StatusCode();
RStringF statusStr = resp.StatusText();
TBuf<32> statusStr16;
statusStr16.Copy(statusStr.DesC());
if (resp.HasBody() && (status >= 200) && (status < 300) && (status != 204))
{
TInt dataSize = resp.Body()->OverallDataSize();
if (dataSize >= 0)
dataSize = dataSize;
else
dataSize = 0;
}
} break;
case THTTPEvent::EGotResponseBodyData:
{
// Get the body data supplier
iRespBody = aTransaction.Response().Body();
TPtrC8 bodyData;
iRespBody->GetNextDataPart(bodyData);
   iBodyBuffer = HBufC8::NewMaxL(iRespBody->OverallDataSize());
   iBodyBufferPtr.Set(iBodyBuffer->Des());
iBodyBufferPtr.Copy(bodyData);


// Done with that bit of body data
iRespBody->ReleaseData();
aTransaction.Close();
CActiveScheduler::Stop();
if(iBodyBufferPtr.Compare(KErrWriteString) != 0 && iBodyBufferPtr.Length() <= 5)
{
TLex8 iLex8ResponseCRC(iBodyBufferPtr);
intCRCResponse = 0;
iResponseCRCMatch = EFalse;
iLex8ResponseCRC.Val(intCRCResponse, EDecimal);
iResponseCRCMatch = (intCRCResponse == iOriginalCRC);

if (iResponseCRCMatch != EFalse)
{
// DISP OK & Closing DLG
WriteToUserLog();
HandleRecognizer(EFalse); // Remove Recognizer from System\Recogs
ShowDialogL(12); // DISP dialog R_BACKUP_OK_MSG_12
ibolHTTPSend = KErrNone;
}
}
if (iResponseCRCMatch  == EFalse || iBodyBufferPtr.Compare(KErrWriteString) == 0 || iBodyBufferPtr.Length() > 5)
{
ShowDialogL(11); // DISP Error dialog R_BACKUP_FAILED_MSG_11
ibolHTTPSend = KErrCancel;
}
} break;
case THTTPEvent::EResponseComplete:
{
} break;
case THTTPEvent::ESucceeded:
{
aTransaction.Close();
CActiveScheduler::Stop();
} break;
case THTTPEvent::EFailed:
{
aTransaction.Close();
CActiveScheduler::Stop();
} break;
case THTTPEvent::ERedirectedPermanently:
{
} break;
case THTTPEvent::ERedirectedTemporarily:
{
} break;
default:
{
if (aEvent.iStatus < 0)
{
aTransaction.Close();
CActiveScheduler::Stop();
ShowDialogL(11); // DISP Error dialog R_BACKUP_FAILED_MSG_11
ibolHTTPSend = KErrCancel;
}
} break;
}
}
So now you have you base, but there are some thing you need to do to start the sending going:
1. Open a Session.
2. Get a pointer to StringPool.
3. Set a pointer to the CallBack class implementing the MHTTPTransactionCallback. In my case I've used the CMECKMAppUi which is actually my AppUI class (CEikAppUi), but you can make a class handling just HTTP if you wan to.
4. Set the HTTP method (e.g. POST).
5. Open a RHTTPTransaction with the relevant method.
6. Set the headers with SetHeaderL() which is described in \examples\appprots\exampleclient. SetMultiPartHeader() is where I set my multipart/form-data types. (I'll come back to it later)
7. Set the request object Body.
8. SetHTTPBody() get the size that I'm counting myself byte by byte. It also copies data to my iReqBodySubmitBuffer[Ptr] where my pointer is pointing to. You dont need to know that.
9. Call SubmitL().
10. Start the active scheduler. (I hope you know that you have to create one. In UIKON you have a default active scheduler a static CActiveScheduler::Current(). Use that one and make a pointer to it.
Code:
RHTTPSession iSess;
RHTTPTransaction iTrans;
RHTTPHeaders iHTTTPHeader;
RStringPool iStringPool;
RStringF iHTTPPostMethod;

iSess.OpenL();
iStringPool = iSess.StringPool();
iTransObs = (MHTTPTransactionCallback*) this;

iHTTPPostMethod = iStringPool.StringF(HTTP::EPOST,RHTTPSession::GetTable());
iTrans = iSess.OpenTransactionL(iUploadURI, *iTransObs, iHTTPPostMethod);
iHTTPPostMethod.Close();
iHTTTPHeader = iTrans.Request().GetHeaderCollection();

SetMultiPartHeader();
// Add headers appropriate to all methods
SetHeaderL(iHTTTPHeader, HTTP::EUserAgent, KUserAgent);
SetHeaderL(iHTTTPHeader, HTTP::EAccept, KAccept);
SetHeaderL(iHTTTPHeader, HTTP::EContentType, iHTTPMultiPartHeader);

MHTTPDataSupplier* dataSupplier = this;
iTrans.Request().SetBody(*dataSupplier);
iHTTPBodySize = SetHTTPBody();
if(iHTTPBodySize == 0) User::Leave(KErrCorrupt); // DISP Error Dialog (e.g.. Shouldn't have to reach this point)
iTrans.SubmitL();
CActiveScheduler::Start();
If you think that we are done, remember this is Symbian OS and not J2ME, so get you're self a bottle of regain (anti hair loss medicine, cause you'll loose a lot of hair as a Symbian developer). (check RFC on HTTP and multipart/form-data):
http://ietf.org/rfc/rfc2616.txt?number=2616
http://ietf.org/rfc/rfc1867.txt?number=1867

Let's look at the Multipart thing:
SetBoundary() creates a pseudo random boundary in the iHTTPBoundary buffer. You have to count all the bytes manually, cause they will end up in the body.
Let's have a lecture on multipart/form-data. You'll need that boundayre I'm talking about when you set your header with SetHeaderL() earlier with iHTTPMultiPartHeader. The boundary itself can be any string (8 bits chars); boundary=ABCD. Your iHTTPMultiPartHeader should then be; "multipart/form-data; boundary=ABCD" and that is your overall content type.
Ok, the boundary is ABCD, but in the body it will be preceded by "--", so
it will look like --ABCD followed by carriage return and linefeed "\r\n".
The you have to add the Content-Disposition: (e.g. a header but in multipart/form-data you have to add it in the body, cause its different for every file), next I add a line with KDispFormData and "\r\n" the integer value (in my case), followed by "\r\n".

I add a new boundary --ABCD + "\r\n". Once more KDisposition followed by KDispUserFile followed by the filename and terminated with a singlequote and ofcourse "\r\n".
Next is the content type for the file itself KMIMETextPlain +"\r\n". Then the bytes in the file youÂ’d like to send, followed by "\r\n". When your done you add the finishing boundary and that has to end with an "--", so --ABCD--
If your not done you keep on adding elements, files separating them with boundary string and all the "\r\n" are vey important, if you miss one, it all goes down the drain. Finish it of with boundary-- (e.g. --ABCD--)
Code:
_LIT8(KMIMETextPlain, "Content-Type: text/plain");
_LIT8(KMIMEMultipart, "multipart/form-data; boundary=");
_LIT8(KDispUserFile,  "form-data; name='userfile'; filename='");
_LIT8(KDispFormData,  "form-data; name='CRC_SYMBIAN'");
_LIT8(KDisposition,   "Content-Disposition: ");
_LIT8(KCrLf,   "\r\n");
_LIT(KBoundaryEnd, "--");

void CMECKMAppUi::SetMultiPartHeader()
{
SetBoundary();
iHTTPMultiPartHeader.Zero();
iHTTPMultiPartHeader.Append(KMIMEMultipart);
iHTTPMultiPartHeader.Append(iHTTPBoundary);
}
TInt CMECKMAppUi::SetHTTPBody()
{
_LIT8(KSingleQuote, "'");

iReqBodySubmitBuffer = HBufC8::NewMaxL(iOriginalBufferPtr.Length() + (iHTTPBoundary.Length()*3) +512);
iReqBodySubmitBufferPtr.Set(iReqBodySubmitBuffer->Des());

iReqBodySubmitBufferPtr.Zero();
iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
iReqBodySubmitBufferPtr.Append(iHTTPBoundary);
iReqBodySubmitBufferPtr.Append(KCrLf);
iReqBodySubmitBufferPtr.Append(KDisposition);
iReqBodySubmitBufferPtr.Append(KDispFormData);
iReqBodySubmitBufferPtr.Append(KCrLf);
iReqBodySubmitBufferPtr.Append(KCrLf);

iReqBodySubmitBufferPtr.AppendNum((int)iOriginalCRC);

iReqBodySubmitBufferPtr.Append(KCrLf);
iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
iReqBodySubmitBufferPtr.Append(iHTTPBoundary);
iReqBodySubmitBufferPtr.Append(KCrLf);
iReqBodySubmitBufferPtr.Append(KDisposition);
iReqBodySubmitBufferPtr.Append(KDispUserFile);
iReqBodySubmitBufferPtr.Append(iSystemCopyFileName);
iReqBodySubmitBufferPtr.Append(KSingleQuote);
iReqBodySubmitBufferPtr.Append(KCrLf);

iReqBodySubmitBufferPtr.Append(KMIMETextPlain);
iReqBodySubmitBufferPtr.Append(KCrLf);
iReqBodySubmitBufferPtr.Append(KCrLf);

iReqBodySubmitBufferPtr.Append(iOriginalBufferPtr);

iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
iReqBodySubmitBufferPtr.Append(iHTTPBoundary);
iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
return iReqBodySubmitBufferPtr.Length();
}
This is a dump:
Quote
Accept-Language: en
Content-Type: multipart/form-data; boundary=ABCD
User-Agent: My Symbian Explorer
Host: www.kundutech.com
Content-Length: 628
Connection: Keep-Alive
Cache-Control: no-cache

--ABCD
Content-Disposition: form-data; name="CRC_SYMBIAN"

12345
--ABCD
Content-Disposition: form-data; name="userfile"; filename="C:\test.txt"
Content-Type: text/plain

My text goes here and it originates from a file on Symbian.
--ABCD--
The size and stuff are not accurate for this example, but it gives you a good guideline.

What you need to know now is. If your GetNextDataPart() is not working properly, the HTTP Host header (look in RFC) will not be added automatically and you'll get Missing Host Header error -7361 (or something like that).
So what happens when youÂ’re active scheduler is called?
1. YOUR virtual OverallDataSize() is called (several times).
2. GetNextDataPart() is called until the buffer is empty (e.g. GetNextDataPart return EFalse)
3. You get a response (hopefully HTTP 200 OK), the MFRunL is called once for headers, once for the body.

You're OverallDataSize() is called then all the initial things are working, remember that it has to respond with the correct content-length otherwise if it's to short all the bytes wonÂ’t be sent, and if it's to long you'll end up with a KErrCorrupt.
If GetNextDataPart() is called and it provides the correct data, then it should work.

Thu, 2006-02-23 15:21
Joined: 2005-11-03
Forum posts: 7
Re: Upload File to a Server using HTTP possible?
hi kundutech,
i see your post was a good while ago. But i'm trying to use your ideas to make a multipart HTTP post.

I was wondering if you could explain some of the variables you  used in example?

-iOriginalBuffer
-iReqBodySubmitBufferPtr
-iOriginalCRC

Your help would be greatly appreciated

Thanks,
Dermot.
Thu, 2006-02-23 15:58
Joined: 2005-01-13
Forum posts: 31
Re: Upload File to a Server using HTTP possible?
Hi Dermot.
The iOriginalBuffer is the content of the file being sent. Look at this:

The packet must include the length using “Content-Length” header and a content type using the “Content-Type” header. While the length is calculated in a pretty straight forward manner the content type for uploading file over HTTP is described in RFC 1867. This header consist of two part, the type it self, “multipart/form-data” and the boundary.

The boundary is used to delimit different parts of data being upload and it is preceded by two dashes “--“. After the boundary each part is described using the “Content-Disposition” header telling the server that it is a “form-data”, not any of the other MIME types, and its name. The header is then followed by two sets of carriage return and linefeed “\r\n\r\n” and then the value. The next part is delimited by the value of boundary preceded by “--”.
Sending a file also includes the “filename” or actually the full path and filename of the file being sent in the “Content-Disposition” header. The header is then followed by a “Content-Type” header for the file it self, which in the example below is “text/plain”. Then the packet has two more sets of carriage return and linefeed followed by the actual content of the file.

When the last part of the multipart/form-data has been added to the packet it is ended with the two dashes, boundary and finally another two dashes.

HTML Code:
<FORM ACTION="http://www.kundutech.com/upload.asp"
      ENCTYPE="multipart/form-data"
      METHOD=POST>
What is your name? <INPUT TYPE=TEXT NAME=submitter>
What files are you sending? <INPUT TYPE=FILE NAME=pics>
</FORM>


iReqBodySubmitBufferPtr corrensponds to the entire request:

POST /upload.asp HTTP/1.1
Host: www.kundutech.com
User-Agent: XXX HTTP
Content-Length: 709

Content-type: multipart/form-data, boundary=AaB03x

--AaB03x
content-disposition: form-data; name="field1"

Joe Blow
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain

... contents of file1.txt ...
--AaB03x—


Now iOriginalCRC is a CRC value that I need as a field, but in the above example it corresponds to the string "Joe Blow".

iOriginalBuffer  corresponds to contents of file1.txt .

Rewriting it would result in iReqBodySubmitBufferPtr =:

[i]POST /upload.asp HTTP/1.1
Host: www.kundutech.com
User-Agent: XXX HTTP
Content-Length: 709

Content-type: multipart/form-data, boundary=AaB03x

--AaB03x
content-disposition: form-data; name="field1"

iOriginalCRC
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain

iOriginalBuffer
--AaB03x—[/b]

I hope that it clear's things up and for more detail look at RFC 1867.

Cheers,
Piotr
www.kundutech.com

PS. Please make a new post if you solved your problem and most importantly how?

Tue, 2006-08-22 13:08
Joined: 2005-07-04
Forum posts: 59
Re: Upload File to a Server using HTTP possible?
Hi kundutech,

Can in the same way I upload an image file also.

Regards.
Tue, 2006-08-22 18:10
Joined: 2005-01-13
Forum posts: 31
Re: Upload File to a Server using HTTP possible?
Yeah.
Sure you can, it's the same thing.

Wed, 2006-08-23 05:49
Joined: 2005-07-04
Forum posts: 59
Re: Upload File to a Server using HTTP possible?
I have read in the nokia forum post

http://discussion.forum.nokia.com/forum/showthread.php?t=82021&highlight=HTTP

That I need to read it into a buffer and then convert it to base 64.
Is that required ?

Also If I run the HttpCLientExample in approots, I can do a get but the posting of a file is failing with -20.
Can you provide some pointers to it.

Thanks.
Wed, 2006-08-23 13:11
Joined: 2005-07-04
Forum posts: 59
Re: Upload File to a Server using HTTP possible?
I am trying to upload a text file the way you have mentioned in your mail by adding the boundary.

I am getting a -20 error.

Attached is the code snippet:

void CClientEngine::SetMultiPartHeader()
   {
   iHTTPBoundary.Copy(_L8("ABCD"));
   iHTTPMultiPartHeader.Zero();
   iHTTPMultiPartHeader.Append(KMIMEMultipart);
   iHTTPMultiPartHeader.Append(iHTTPBoundary);
   }

TInt CClientEngine::SetHTTPBody()
   {
   _LIT8(KSingleQuote, "'");
   
   TInt err = iReqBodyFile.Read(iPostData->Des());
   iReqBodySubmitBuffer = HBufC8::NewMaxL(iPostData->Des().Length() + (iHTTPBoundary.Length()*3) +512);
   iReqBodySubmitBufferPtr.Set(iReqBodySubmitBuffer->Des());

   iReqBodySubmitBufferPtr.Zero();
   iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
   iReqBodySubmitBufferPtr.Append(iHTTPBoundary);
   iReqBodySubmitBufferPtr.Append(KCrLf);
   iReqBodySubmitBufferPtr.Append(KDisposition);
   iReqBodySubmitBufferPtr.Append(KDispFormData);
   iReqBodySubmitBufferPtr.Append(KCrLf);
   iReqBodySubmitBufferPtr.Append(KCrLf);

//   iReqBodySubmitBufferPtr.AppendNum((int)iOriginalCRC);

   iReqBodySubmitBufferPtr.Append(KCrLf);
   iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
   iReqBodySubmitBufferPtr.Append(iHTTPBoundary);
   iReqBodySubmitBufferPtr.Append(KCrLf);
   iReqBodySubmitBufferPtr.Append(KDisposition);
   iReqBodySubmitBufferPtr.Append(KDispUserFile);
   iReqBodySubmitBufferPtr.Append(_L8("test.txt"));
   iReqBodySubmitBufferPtr.Append(KSingleQuote);
   iReqBodySubmitBufferPtr.Append(KCrLf);

   iReqBodySubmitBufferPtr.Append(KMIMETextPlain);
   iReqBodySubmitBufferPtr.Append(KCrLf);
   iReqBodySubmitBufferPtr.Append(KCrLf);

   iReqBodySubmitBufferPtr.Append(iPostData->Des());

   iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
   iReqBodySubmitBufferPtr.Append(iHTTPBoundary);
   iReqBodySubmitBufferPtr.Append(KBoundaryEnd);
   return iReqBodySubmitBufferPtr.Length();
   }



TBool CClientEngine::GetNextDataPart(TPtrC8& aDataPart)
   {
   TBool retVal = EFalse;
   TInt err = iReqBodyFile.Read(iPostData->Des());
   if (err == KErrNone)
      {
      aDataPart.Set(iPostData->Des().Ptr());
      //++iDataChunkCount;
      retVal = (iPostData->Des().Length() == 0);
      }
   return retVal;
   }

Is there anything that I am missing.

Wed, 2006-08-23 13:44
Joined: 2005-07-04
Forum posts: 59
Re: Upload File to a Server using HTTP possible?
Was able to successfully upload the file.
There was problem with the GetNextDataPart().
Actually I was transferring data from the file rather than from
iReqBodySubmitBufferPtr.

Thanks a lot.
Any inside into uploading of image stuff.
Wed, 2006-11-08 12:35
Joined: 2006-04-25
Forum posts: 19
Re: Upload File to a Server using HTTP possible?
Hi tinatibrewal ,

             Can you tell me which Application you are using for the Web Server.also my problem is that i dont know how to set the uri......


For your reference.. am using this .................
url.Copy(_L("http://xxx.x.xx.xxx/MailWebService/Service1.asmx?op=AddStr"));

But the web server is expecting the content of the file which I want to post on the web server as the value of the variable.

Please guide me ...........

Thanx in Advance...

Regards,
Brajesh

Sat, 2006-11-25 06:50
Joined: 2005-07-04
Forum posts: 59
Re: Upload File to a Server using HTTP possible?
Sorry for the late reply..
I was uploading it to an internal webserver designed by us.
So didnt face any such problem.
Sun, 2006-11-26 15:35
Joined: 2006-11-07
Forum posts: 5
Re: Upload File to a Server using HTTP possible?
Hi, guys.

I also have to upload mulitple files to some server.

I faced some strange problems there:

1. At first, I performed regular HTTP post with all required headers and in GetNextDataPart() I put the being uploaded file content:
Code:
TBool CXXEngine::GetNextDataPart(TPtrC8& aDataPart)
{
  if(iPostData)
  {
// Provide pointer to next chunk of data (return ETrue, if last chunk)
// Usually only one chunk is needed, but sending big file could require
// loading the file in small parts.
aDataPart.Set(iPostData->Des());
  }
return ETrue;
}
void CXXEngine::ReleaseData()
{
  if(iPostData)
  {
delete iPostData;
iPostData = NULL;
}

}


It worked well in case of single upload (i.e. after each file upload some other HTTP GET was performed).
It also worked well on files with different sizes fom 500 bytes till Kb and Mb.

2.After that I had to implement upload sequence of multiple files. Here the problems started.

The process looks like that:
MyAppUi (to make things simple) called some UploadFoo(...) (like well-known IssueHTTPPostL(...) from HTTP example). This function performed all necessary transaction/headers/SubmitL()/etc. stuff. When I received ESucceeded/EFailed I notified AppUi about that and AppUi after 1sec timer called UploadFoo() again to upload next file (in timer thread).

On emulator worked fine, but on the device (N80) sometimes the application was closed. After some research I noticed that after several uploaded files ReleaseData() was not called. And after that on 2nd or 3rd file upload the application simple hang up.

After some additional research I tried to upload many files with less-than-1k length and "voila" - every file was uploaded.

My conclusion was that I had to divide my file content to chunks.
(I still don't understand why it works when i upload only one large file?Huh?)

I looked at HTTPEXAMPLECLIENT, at very useful posts of Piotr Kundu and reimplemented the GetNextDataPart() and ReleaseData() functions.

Now every time GetNextDataPart(TPtrC8& aDataPart) is called, I put into aDataPart next chunk of file content
Code:
TBool CXXEngine::GetNextDataPart(TPtrC8& aDataPart)
{
TBool bRetVal = EFalse;
if(iPostData)  // whole file buffer - HBufC8*
{
iPostDataChunk->Des().Zero(); // 1K HBufC8* that created in UploadFoo()
TInt nTotalLen = iPostData->Des().Length();
TInt nLastPos = inDataChunkCount*KMaxSubmitSize; // KMaxSubmitSize - 1024
TInt nNewPos = (inDataChunkCount+1)*KMaxSubmitSize;
if(nNewPos > nTotalLen)
{
if(nLastPos > nTotalLen)
{
bRetVal = ETrue;
iPostDataChunk->Des().Copy(_L(""));
}
else
{
iPostDataChunk->Des().Copy( iPostData->Des().Mid(nLastPos) );
inDataChunkCount++;
}
}
else
{
iPostDataChunk->Des().Copy( iPostData->Des().Mid((inDataChunkCount*KMaxSubmitSize), KMaxSubmitSize) );
inDataChunkCount++;
}

aDataPart.Set(iPostDataChunk->Des());
}
else
{
bRetVal = ETrue;
}

// return true if last chunk
return bRetVal;

}

The ReleaseData() function changed also:

Code:
void CXXEngine::ReleaseData()
{
// Clear out the submit buffer
iPostDataChunk->Des().Zero();
ibReleased = ETrue;
// Notify HTTP of more data available immediately, since it's being read from file
TRAPD(err, iTransaction.NotifyNewRequestBodyPartL());
if (err != KErrNone)
{
_LIT(KNotifyNewRequestBodyPart, "NotifyNewRequestBodyPartL left");
iObserver.StateChanged(eStateUnrecognisedEvent, KNotifyNewRequestBodyPart);
}
}


I received -20  Embarassed

The questions are:
- If I divide my file content to chunks, should I implement multipart/form-data upload or I can simple set next chunk of data in GetNextDataPart()?

- I saw also that GetNextDataPart is called twice without ReleaseData() is called - is it ok?

I'm struggling with it couple of days...
I miss something very basic here.....
Any help will be more than appreciated.

Regards,
Genady
Sun, 2006-11-26 22:00
Joined: 2006-11-07
Forum posts: 5
Re: Upload File to a Server using HTTP possible?
I found the problem. It's not directly related to file size.

As I said, I'm trying to upload multiple files to the server each after another.

When I submit HTTP POST transaction I put some information into custom headers. When server recieve incoming HTTP POST request it can decide to receive or not this file (it can be decided after headers observation).

That was happened in my case. Server received only headers and decided not to accept the file and returned "200 OK" without waiting for HTTP POST request body. It caused crash in some of Symbian HTTP stack related components after 2nd or 3rd subsequent upload.

What I would expect to get is some Error notification in MHFRunError(...) or in MHFRunL(...) callbacks - I receive nothing strange - EGotResponseHeaders, EGotResponseBodyData, EResponseComplete, ESucceeded.

It seems like a Symbian bug.

Regards,
Genady
Thu, 2007-01-04 15:08
Joined: 2007-01-04
Forum posts: 3
Re: Upload File to a Server using HTTP possible?
Hello, did you get to work out with the HTTP POST ? I need some help with it. I'm getting stuck with a E32USER-CBASE 42 error ( I used Panix to find it out ) right before MHFRunL get called to notify a EGotResponseHeaders event.

Any ideas of what I can do to work this out ?

Thanks !!
Fri, 2007-01-05 13:34
Joined: 2005-07-04
Forum posts: 59
Re: Upload File to a Server using HTTP possible?
User 42 panic is raised when :
This panic is raised by the SetActive() member function of an active object, a CActive. It is caused by an attempt to flag the active object as active when it is already active, i.e. a request is still outstanding.

Try pasting some portion of your code and then somebody might be able to help you.
  • Login to reply to this topic.