【问题标题】:Resume file Upload to wcf rest service when connection fails连接失败时恢复文件上传到 wcf rest 服务
【发布时间】:2013-06-08 04:54:26
【问题描述】:

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

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

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

我如何修改其余服务以提供一种工具来上传已停止的文件。如何添加 Range 和 Content Range 标头以向客户端提供此信息。 如果有简历上传过程的示例代码,请提供代码。

【问题讨论】:

    标签: wcf file-upload


    【解决方案1】:

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

    我们的方法是创建两个附加方法,一个由客户端设备调用以检查先前上传的状态(称为“GetStatusOfLastUpload(SessionID, DeviceID, FileID)”),另一个称为 ResumeUpload(SessionID, DeviceID, FileID, MD5Hash, Bytes).

    函数 GetStatusOfLastUpload 顾名思义,向主机发送一个附加请求以检查先前上传的状态(存储在 SQL 数据库中)。

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

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

    这里无法包含所有示例代码,但我会说我们的 ResumeUpload 函数看起来与我们的 Upload 函数相同,但包含一些额外的检查以确保一切正确。 ______________________编辑______________________ 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

    【讨论】:

    • 你对内容范围和范围标题有什么想法吗?如果您有想法,请告诉我在服务器端和客户端实现它们的方法。
    • 能否给我详细的wcf服务代码和客户端代码
    猜你喜欢
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    相关资源
    最近更新 更多