3

I have the following problem.

I have a ActiveX control written in C++/CLI, which I'm using on client side. one of the control method return binary file by fixed chunk size (for example by 1024). This file is zipped.

I need to write method using C++/CLI which will send each file chunk to the server. I have Java Spring MVC method which receives this byte[] chunk and append it to file. In other words I'm just uploading zip file by chunks.

My problem is, that although the file size of both files (Original and its copy on server) ,the MD5 checksum of this file is not the same and I can't open this file using zip. The file is corrupted.

I'm just taking each chunk byte[] convert it with BASE64 and send it to server using my regular POST request:

My code is the following:

int SceneUploader::AddChunk(int id, array<Byte> ^buffer,int size){
WebRequest^ request = WebRequest::Create(AddChunkURI);
request->Method = "POST";
request->ContentType = "application/x-www-form-urlencoded";
System::String ^base64Image = Convert::ToBase64String(buffer);
String ^param = "id="+id+"&chunk="+base64Image+"&len="+size;

//Just make another copy of the file to verify that sent byted are ok!!!
String ^path = "C:\\Users\\dannyl\\AppData\\Local\\Temp\\test.zip";
FileStream ^MyFileStream = gcnew FileStream(path, FileMode::Append, FileAccess::Write);
MyFileStream->Write(buffer,0,size);
MyFileStream->Close();
//Adding the byteArray to the stream.
    System::IO::Stream ^stream = request->GetRequestStream();
    System::IO::StreamWriter ^streamWriter = gcnew System::IO::StreamWriter(stream);
    streamWriter->Write(param);
    streamWriter->Close();
    HttpWebResponse^ response = dynamic_cast<HttpWebResponse^>(request->GetResponse());
    Stream^ dataStream = response->GetResponseStream();
    StreamReader^ reader = gcnew StreamReader( dataStream );
    String^ responseFromServer = reader->ReadToEnd();
    return System::Int32::Parse(responseFromServer);
}

My MVC controller looks like this:

 @RequestMapping(value="/addChunk.dlp",method = RequestMethod.POST)
      @ResponseBody
         public String addChunk(@RequestParam("id") String id,
                 @RequestParam("chunk") String chunk,
                 @RequestParam("len") String len){
            try{
                 BASE64Decoder decoder = new BASE64Decoder();
                 Integer length = Integer.decode(len);
                 byte[] decodedBytes = new byte[length];
                 decodedBytes = decoder.decodeBuffer(chunk.trim());
                 File sceneFile = new File(VAULT_DIR+id+".zip");
                 if (!sceneFile.exists()){
                     sceneFile.createNewFile();
                 }
                 long fileLength = sceneFile.length(); 
                    RandomAccessFile raf = new RandomAccessFile(sceneFile, "rw"); 
                    raf.seek(fileLength);            
                    raf.write(decodedBytes); 
                    raf.close();                  
            }
            catch(FileNotFoundException ex){
            ex.getStackTrace(); 
            System.out.println(ex.getMessage());
            return "-1";
            }
            catch(IOException ex){
                ex.getStackTrace();
                System.out.println(ex.getMessage());
                return "-1";
                }

            return "0";
         }

What am I doing wrong?

Update: the problem solved. Original Base64 String had '+' characters, after the request was submitted to server the chunk parameter was URLdecoded by Spring and all'+' characters were replaced by spaces, as a result zip file was corrupted. Please give me back my +50 of reputation :)

Thank you, Danny.

danny.lesnik
  • 18,479
  • 29
  • 135
  • 200
  • Tag changed from "C++" to "C++/CLI". Despite similar syntax in many places, these are really different languages; C++/CLI has more in common with C# than it does C++. – Billy ONeal Dec 15 '10 at 00:24
  • I suggest you try uploading a simple file, then a simple file using base64, then a zipped file using base64. I have had base64 encoding and decoding problems in the past. This is just to be sure that base64 interconversion is happening correctly on both sides. – Abhijeet Kashnia Dec 15 '10 at 10:00
  • How can I send byte array in HTTP request without encoding it with base64? – danny.lesnik Dec 15 '10 at 11:18
  • Yes, now I see that sending data without base64 encoding will be unreliable. http://stackoverflow.com/questions/3538021 . I thought that you could read data you want to send using a stream, open up the web request object's stream with "Stream requestStream = webRequest.GetRequestStream()", then a "BinaryWriter bw = new BinaryWriter(requestStream)" so that binary writer will point to request stream. Now, use a byte array to read from your data stream and write to binary writer with "bw.Write(buffer, 0, readLength)". But I think what I have suggested is wrong since binary data is better encoded. – Abhijeet Kashnia Dec 16 '10 at 07:29
  • The problem solved, see my last update. Thank you. – danny.lesnik Dec 20 '10 at 22:58

1 Answers1

0

I have not experienced about your client-side for sending file to server with HTTP.

In server side, however, you may check out the Spring MVC Multipart. And in client side, sending file with Multipart is another way to achieve your goal.

Mike Lue
  • 839
  • 4
  • 8
  • Ok, but I'm not uploading file, but just a chunk of it as byte[], this is the reason why I haven't sent it as multipart. – danny.lesnik Dec 15 '10 at 07:49