2012-04-22 16 views
1

Webサービスでファイルを転送するタスクを使用するコードが少しあります。ただし、ネットワークが切断されたり、タイムアウトが発生したりすると、不完全なファイルが作成されます。私は本当にこのサービスを可能な限り信頼できるものにしようとしていますが、チャンクが送信されなかったときにトラップするコードをどこに追加してから、何度も再送信しようとしますそれが完了するまで、次のチャンクを送ります。 X回以上チャンクを再送信できない場合は、完全に失敗してイベントを記録してください。Webサービスのファイル転送、再試行の追加方法?

誰もが何か示唆できますか?

Action<Guid, string> action = (smGuid, pubAttFullPath) => 
     { 
      try 
      { 
       //Set filename from object 
       string FileName; 
       FileName = System.IO.Path.GetFileName(pubAttFullPath.ToString()); 

       //Declare Web Service 
       TransferFile.TransferFileSoapClient ws_TransferFile = new TransferFile.TransferFileSoapClient(); 

       // 
       bool transfercompleted = false; 
       using (FileStream fs = new FileStream(
        pubAttFullPath.ToString(), 
        FileMode.Open, 
        FileAccess.Read, 
        FileShare.Read)) 
       { 
        //Declare Buffers and Counts 
        byte[] buffer = new byte[49152]; 
        long fileSize = fs.Length; 
        long totalReadCount = 0; 
        int readCount; 
        float percentageComplete = 0; 

        //Loop and copy file until it changes to not exactly the same byte count as the buffer 
        //which means the file is about to complete. 
        while ((readCount = fs.Read(buffer, 0, buffer.Length)) > 0) 
        { 
         if (!transfercompleted) 
         { 

          totalReadCount += readCount; 
          byte[] bytesToTransfer; 

          if (readCount == buffer.Length) 
          { 
           //Copy bytes until buffer is different 
           bytesToTransfer = buffer; 
           ws_TransferFile.WriteBinaryFile("ABCD", bytesToTransfer, FileName); 
           percentageComplete = (totalReadCount/(float)fileSize * 100); 
           percentageComplete = (float)Math.Round(percentageComplete, 2, MidpointRounding.ToEven); 
           //Update progress to DB 

           InsertProgress.InsertProgressSoapClient ws_InsertProgress = new InsertProgress.InsertProgressSoapClient(); 
           if (percentageComplete == 10.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 10.0); 
           } 
           if (percentageComplete == 20.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 20.0); 
           } 
           if (percentageComplete == 30.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 30.0); 
           } 
           if (percentageComplete == 40.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 40.0); 
           } 
           if (percentageComplete == 50.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 50.0); 
           } 
           if (percentageComplete == 60.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 60.0); 
           } 
           if (percentageComplete == 70.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 70.0); 
           } 
           if (percentageComplete == 80.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 80.0); 
           } 
           if (percentageComplete == 90.00) 
           { 
            ws_InsertProgress.InsertProgressService(smGuid.ToString(), 90.0); 
           } 
          } 
          else 
          { 
           // Only a part is requred to upload, 
           // copy that part. 
           List<byte> b = new List<byte>(buffer); 
           bytesToTransfer = b.GetRange(0, readCount).ToArray(); 
           ws_TransferFile.WriteBinaryFile("ABCD", bytesToTransfer, FileName); 
           percentageComplete = 100; 

           //Insert Progress as complete 
           InsertProgress.InsertProgressSoapClient ws_InsertProgress = new InsertProgress.InsertProgressSoapClient(); 
           ws_InsertProgress.InsertProgressService(smGuid.ToString(), 100); 
           transfercompleted = true; 
           fs.Close(); 
           break; 
          } 
         } 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       EventLog.WriteEntry("Application", ex.Message.ToString(), EventLogEntryType.Error); 
      } 

答えて

0

Webサービスはファイル転送には悪い考えです。私はそれを数回使用しましたが、追加データ転送量は、転送されるデータのサイズを単純なハンドラを使用してファイルを送信してから1.5-2倍大きくしています。ハンドラは問題なしで同じことを可能にします。適切な進捗状況の処理と再開で多くの問題を引き起こします。あなたは本当にhttphandlerを使って再考すべきです。あなたがWebサービスを使用したい場合は、ここでは良い例です。

http://msdn.microsoft.com/en-us/library/ms172362%28v=vs.85%29.aspx

あなたはIHTTPハンドラを参照してください使用する場合:

http://msdn.microsoft.com/en-us/library/ms228090%28v=vs.100%29.aspx

をそしてあなたに次のコードを使用することができます適切なハンドルの再試行/再開:

   using (Stream stream = new FileStream(
       pubAttFullPath.ToString(), 
       FileMode.Open, 
       FileAccess.Read, 
       FileShare.Read)) 
       { 
        context.Response.AddHeader("Accept-Ranges", "bytes"); 
        context.Response.Buffer = false; 

        if (context.Request.Headers["Range"] != null) 
        { 
         context.Response.StatusCode = 206; 
         string[] range = context.Request.Headers["Range"].Split(new[] { '=', '-' }); 
         startBytes = Convert.ToInt32(range[1]); 
        } 

        int dataToRead = size - startBytes; 

        context.Response.ContentType = "application/octet-stream"; 
        context.Response.AddHeader("Content-Length", dataToRead.ToString()); 
        context.Response.AddHeader("Connection", "Keep-Alive"); 
        context.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8)); 

        if (startBytes > 0) 
        { 
         context.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, size - 1, size)); 
         stream.Seek(startBytes, SeekOrigin.Begin); 
        } 

        while (dataToRead > 0) 
        { 
         // Verify that the client is connected. 
         if (context.Response.IsClientConnected) 
         { 
          // Read the data in buffer. 
          int length = stream.Read(buffer, 0, buffer.Length); 

          // Write the data to the current output stream. 
          context.Response.OutputStream.Write(buffer, 0, length); 

          // Flush the data to the HTML output. 
          context.Response.Flush(); 
          dataToRead = dataToRead - length; 
         } 
         else 
         { 
          // prevent infinite loop if user disconnects 
          dataToRead = -1; 
         } 
        } 
       } 
+0

あなたの返信!私はWebサービスを使用して気づいた、それは私が思うよりずっと遅かった。しかし、もしこれをIHTTPHandlerとして書くとしたら、あなたのクライアントコードの例では、サーバー側のコードはどのように見えますか? IHTTPHandler情報へのリンクはかなり一般的です。 –

+0

私のサンプルは、ダウンロード再開をサポートするために処理しているproerヘッダで使用しているハンドラの一部です。しかし、このハンドラを適切に呼び出すためにはrememebrを使う必要があります。また、クライアントは適切に再構築をサポートする必要があるため、クライアント側では、すでにダウンロードされているデータの数をサーバーに知らせるために正しいヘッダーを置く必要があります。 – Marcin

+0

Marcin - 私は自分のコードでIHttpHandlerの設定を実装しましたが、何らかの進捗報告を実装しようとしていますが、これを実行する最善の方法を提案できますか?私は自分のコードをhttp://stackoverflow.com/questions/10471127/ihttphandler-file-transfer-progressに入れました。 –

関連する問題