恢复文件连接失败时上传到wcf rest服务

时间:2013-06-12 06:55:40

标签: wcf file-upload

我正在尝试将大型文件从android上传到wcf rest服务。我能够正确上传文件。但我的问题是当从android上传文件到服务器连接失败时,我无法恢复上传过程。再次上传从头开始可以任何人告诉我写wcf休息服务的方式,我可以恢复我的上传过程。

我目前正在使用以下休息服务上传数据:

  public string PostImage(Stream stream)
        {
            try
            {


                byte[] buff = new byte[50485760];
                using (FileStream fs = new FileStream(System.Web.HttpContext.Current.Server.MapPath(@"~/Images/" + "filename"), FileMode.Create))
                {
                    int bytesRead = stream.Read(buff, 0, buff.Length);
                    while (bytesRead > 0)
                    {
                        fs.Write(buff, 0, bytesRead);
                        bytesRead = stream.Read(buff, 0, buff.Length);
                    }
                }
            }
            catch (Exception e)
            {

            }
            //Class1 parser = new Class1(stream);
            return "Recieved the image on server";
        } 

如何修改其余服务以提供上传停止文件的工具。如何添加范围和内容范围标头以向客户端提供此信息。 如果有任何恢复上传过程的示例代码,请提供代码。

1 个答案:

答案 0 :(得分:1)

我刚刚实现了这样的东西。如果上传失败或只有一半的字节到达主机,你会怎么做?

我们的方法是创建另外两种方法,一种是客户端设备调用以检查先前上载的状态(称为“ GetStatusOfLastUpload(SessionID,DeviceID,FileID)”),另一种称为< strong> ResumeUpload(SessionID,DeviceID,FileID,MD5Hash,Bytes)。

函数 GetStatusOfLastUpload 执行名称所暗示的操作,向主机发送附加请求以检查先前上载的状态(存储在SQL数据库中)。

此过程的关键是使用计算的MD5哈希和字节计数在主机端确定是否已传递完整文件。例如,如果客户端发送1MB,但主机仅获得500KB,并且客户端发送的MD5哈希与主机根据接收的字节计算的MD5不匹配,我们将上载数据记录的状态设置为“Imcomplete” “并存储字节数。因此,当调用 GetStatusOfLastUpload 时,主机返回(如果需要)上次上载为“Imcomplete”并且收到的字节数仅为500KB。

然后,客户端应用程序从 GetStatusOfLastUpload 获取此信息并调用“ ResumeUpload ”,发送完整文件的MD5哈希以及主机所需的剩余字节。接收到主机后,主机再次组合字节并计算MD5哈希值,并将其与客户端发送的值进行比较。如果哈希值匹配,您知道您有一个完整的文件,如果没有,请重复该过程。

这里没有办法包含所有示例代码,但我会说我们的ResumeUpload函数看起来与我们的上传函数相同,但包含一些额外的检查以确保一切正确。 的 _ __ _ __ _ __ _ __ _ __ _ __ _ ___ 修改 _ __ _ __ < EM> _ __ _ __ _ __ _ __ _ __ _ __ _ _

我们在客户端使用.NET的东西,但这是一些示例Java代码(更适合Android)我为那些在非Windows设备上开发的人提供了代码。它构造了与WCF主机(也是.NET)交换的消息。

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;
    }
}

在主机方面,要分享的代码太多,但概念在上面的帖子中。需要记住的是,WCF(几乎)始终是客户端请求/主机响应方案,因此客户端设备需要启动所有内容,包括检查上次上载是否成功。按照我的建议去做?

这可能是您的良好信息来源:http://fszlin.dymetis.com/post/2010/05/10/Comsuming-WCF-Services-With-Android.aspx