Hi, guys.
I 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??)
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
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




