0

我正在尝试将一个大文件从 android 上传到 wcf 休息服务。我能够正确上传文件。但我的问题是当将文件从 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";
        } 

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

4

1 回答 1

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 函数相同,但包含一些额外的检查以确保一切正确。 _ __ _ __ _ __ _ __ _ __ _ __ _ ___编辑_ __ _ __ _ __ _ __ _ _ _ __ _ __ _ __ _ _

我们在客户端使用 .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

于 2013-06-12T08:42:56.817 回答