Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I've just implemented something like this. If the upload fails or only half the bytes arrive at the host, what do you do? </p> <p>Our approach was to create two additional methods, one that the client device calls to check the status of the prior upload (called "<strong>GetStatusOfLastUpload(SessionID, DeviceID, FileID)</strong>") and another called <strong>ResumeUpload(SessionID, DeviceID, FileID, MD5Hash, Bytes)</strong>.</p> <p>The function <strong>GetStatusOfLastUpload</strong> does what the name implies, sending an additional request to the host to check the status (stored on a SQL database) of a prior upload. </p> <p>Key to this process is using a calculated MD5 Hash and byte counts to determine on the host side if the complete file was delivered. For example, if the client sends 1MB, but the Host only gets 500KB and the MD5 hash sent from the client does not match the MD5 calculated by the host based on the bytes received, we set the status of the upload data record to "Imcomplete" and store the byte count. So when <strong>GetStatusOfLastUpload</strong> is called, the Host returns (if necessary) that the last upload was "Imcomplete" and that the byte count received was just 500KB. </p> <p>The client app then takes this information from <strong>GetStatusOfLastUpload</strong> and calls "<strong>ResumeUpload</strong>", sending an MD5 hash of the complete file and the remaining bytes that the host needs. The host again, on receiving this, combines the bytes and calculates the MD5 hash, comparing that to the value sent by the client. If the hash values match, you know you have a complete file, if not, repeat the process. </p> <p>There's no way, here, to include all the sample code, but I'll say that our ResumeUpload function looks identical to our Upload function, but includes a few extra checks to ensure everything is correct. <strong><em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>___</strong><em>edit</em><strong><em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>__<em>_</em>_</strong></p> <p>We use .NET stuff on the client side, but this is some sample Java code (better for Android) I put togeter for those developing on non Windows devices. It constructs the message that's exchanged with the WCF host (also .NET).</p> <pre><code>public MsgStruct CallHost(String URL, String Content, byte[] outBytes){ String textValue=""; byte[] inBytes =new byte[] {0}; try { // Creating a new empty SOAP message object SOAPMessage reqMsg = MessageFactory.newInstance().createMessage(); // Populating SOAP body SOAPEnvelope envelope = reqMsg.getSOAPPart().getEnvelope(); SOAPBody body = envelope.getBody(); SOAPBodyElement service = body.addBodyElement(envelope.createName("HostConnect", "", WCFNameSpace)); //good here SOAPElement paramInMsg = service.addChildElement(envelope.createName("inMsg", "", "")); //good here //SOAPElement paramBodySection = paramInMsg.addChildElement(envelope.createName("BodySection", "", DataContractNameSpace)); SOAPElement paramTextSection = paramInMsg.addChildElement(envelope.createName("TextSection", "", DataContractNameSpace)); SOAPElement paramBodySection = paramInMsg.addChildElement(envelope.createName("BodySection", "", DataContractNameSpace)); //get the byte array to send and populate the fields String sOut=org.apache.commons.codec.binary.Base64.encodeBase64String(outBytes); paramBodySection.addTextNode(sOut); //adding the binary stuff here "AA==" paramTextSection.addTextNode(Content); //adding the text content here envelope.removeAttribute("Header"); envelope.setPrefix("s"); envelope.getBody().setPrefix("s"); // Setting SOAPAction header line MimeHeaders headers = reqMsg.getMimeHeaders(); headers.addHeader("SOAPAction", SoapAction); //good here headers.setHeader("Content-Type", "text/xml; charset=utf-8"); //good here headers.setHeader("Host", "Localhost:8085"); //good here headers.setHeader("Expect", "100-continue"); // Connecting and Calling SOAPConnection con = SOAPConnectionFactory.newInstance().createConnection(); SOAPMessage resMsg = con.call(reqMsg, URL); resMsg.saveChanges(); con.close(); //check the host response if (resMsg != null){ try{ SOAPBody responseBody = resMsg.getSOAPBody(); SOAPBodyElement responseElement0= (SOAPBodyElement)responseBody.getChildElements().next(); SOAPElement responseElement1 = (SOAPElement)responseElement0.getChildElements().next(); SOAPElement TextElement = (SOAPElement)responseElement1.getFirstChild(); SOAPElement bodyElement = (SOAPElement)responseElement1.getLastChild(); Node nodeBody = (Node)bodyElement; inBytes = getBytesFromDoc(nodeBody); textValue = TextElement.getTextContent(); }catch (SOAPException se){ String smessage = se.getMessage(); } return new MsgStruct(textValue,inBytes); //no response from host }else{ Debug.println("error","Error- nothign found"); return null; } } catch (Exception e) { Debug.println("error",e.getMessage()); return null; } } </code></pre> <p>On the host side, there's just too much code to share, but the concept is in the posting above. The thing to keep in mind is that WCF is (almost) always a Client Request/Host Response scenario, so the client device needs to initiate everything, including a check to see if the last upload was successful. Follow what I'm suggesting?</p> <p>This might be a good source of information for you: <a href="http://fszlin.dymetis.com/post/2010/05/10/Comsuming-WCF-Services-With-Android.aspx" rel="nofollow">http://fszlin.dymetis.com/post/2010/05/10/Comsuming-WCF-Services-With-Android.aspx</a></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload