2017-09-27 49 views
9

Chúng tôi có dịch vụ WCF chấp nhận luồng từ máy khách (máy khách tải tệp lên máy chủ). Tuy nhiên, nếu máy chủ ném một FaultException trước hoặc trong luồng khách hàng chỉ mang trên streaming cho đến khi kết thúc bất kể, tại thời điểm đó nó nhận được FaultException từ máy chủ - lãng phí thời gian & băng thông cho khách hàng.WCF - Hủy bỏ luồng từ máy khách đến máy chủ nếu máy chủ ném một FaultException

Câu hỏi tương tự:

How to Abort a WCF File Upload from the Server-Side Method

Đi như sau (dịch vụ WCF đơn giản hóa)

Namespace JP_WCF 
    <ServiceContract> _ 
    Public Interface IJP_WCF 
     <OperationContract> _ 
     <FaultContract(GetType(JP_WCF_Fault))> _ 
     Sub UploadFile(request As JP_WCF_FileUpload) 

     <OperationContract> _ 
     <FaultContract(GetType(JP_WCF_Fault))> _ 
     Function fakeError(ByVal int1 As Integer, ByVal int2 As Integer) As Integer 

     <OperationContract> _ 
     <FaultContract(GetType(JP_WCF_Fault))> _ 
     Function Ping() As Date 
    End Interface 

    <MessageContract> _ 
    Public Class JP_WCF_FileUpload 
     Implements IDisposable 

     <MessageHeader(MustUnderstand:=True)> _ 
     Public FileName As String 

     <MessageHeader(MustUnderstand:=True)> _ 
     Public Length As Long 

     <MessageBodyMember(Order:=1)> _ 
     Public FileByteStream As System.IO.Stream 

     Public Sub Dispose() Implements IDisposable.Dispose 
      If FileByteStream IsNot Nothing Then 
       FileByteStream.Close() 
       FileByteStream = Nothing 
      End If 
     End Sub 
    End Class 

    <DataContract> _ 
    Public Class JP_WCF_Fault 
     <DataMember> _ 
     Public Property EventID() As Integer 
     <DataMember> _ 
     Public Property Message() As String 
     <DataMember> _ 
     Public Property Description() As String 

     Public Sub New(ByVal _EventID As Integer, ByVal _Message As String, ByVal _Description As String) 
      Me.EventID = _EventID 
      Me.Message = _Message 
      Me.Description = _Description 
     End Sub 
    End Class 

End Namespace 

Ví dụ máy chủ phương pháp:

Try 
    Dim sourceStream As Stream = request.FileByteStream 
    Dim uploadFolder As String = "C:\upload\" 
    Dim filePath As String = Path.Combine(uploadFolder, request.FileName) 

    Using targetStream = New FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None) 
     sourceStream.CopyTo(targetStream) 
     targetStream.Close() 
     sourceStream.Close() 
    End Using 
Catch ex As Exception 
    Throw New FaultException(Of JP_WCF_Fault)(New JP_WCF_Fault(8, ex.Message, ex.ToString), ex.Message) 
End Try 

Ví dụ khách hàng Phương pháp:

Dim fileInfo As New System.IO.FileInfo(filePath) 
Dim startTime As DateTime = DateTime.Now 
Console.WriteLine("Starting V2 upload: " + DateTime.Now.ToString()) 

Dim JPCS As New JP_WCFService.JP_WCFClient() 

Using stream As New System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read) 
    Using uploadStreamWithProgress As New JP_StreamWithProgress(stream) 
     AddHandler uploadStreamWithProgress.ProgressChanged, AddressOf uploadStreamWithProgress_ProgressChanged 
     Try 
      JPCS.UploadFile(fileInfo.Name, fileInfo.Length, uploadStreamWithProgress) 
     Catch ex As FaultException(Of JP_WCFService.JP_WCF_Fault) 
      Console.WriteLine("Upload Error: " & ex.Detail.Message & " (EventID: " & ex.Detail.EventID.ToString & ")") 
     End Try 
    End Using 
End Using 
Dim endTime As DateTime = DateTime.Now 
Dim durationInMS As Double = (endTime - startTime).TotalMilliseconds 
Console.WriteLine(vbCr & "V2 Upload Completed: " + DateTime.Now.ToString() + " (" + durationInMS.ToString() + ")") 
JPCS.Close() 

web.config

<system.serviceModel> 
    <bindings> 
     <customBinding> 
      <binding name="JP_WCFBinding"> 
       <!-- maxReceivedMessageSize 600MB, maxBufferSize 2MB --> 
       <binaryMessageEncoding compressionFormat="GZip" /> 
       <httpsTransport transferMode="Streamed" maxReceivedMessageSize="629145600" maxBufferSize="2097152"/> 
      </binding> 
     </customBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="JP_WCFbehavior" name="JP_WCF.JP_WCFServices"> 
      <endpoint address="" binding="customBinding" bindingConfiguration="JP_WCFBinding" contract="JP_WCF.IJP_WCF"/> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="JP_WCFbehavior"> 
       <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" /> 
       <serviceDebug includeExceptionDetailInFaults="true" /> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
</system.serviceModel> 

app.config

<system.serviceModel> 
    <bindings> 
     <customBinding> 
      <binding name="CustomBinding_IJP_WCF"> 
       <binaryMessageEncoding compressionFormat="GZip" /> 
       <httpsTransport transferMode="Streamed" /> 
      </binding> 
     </customBinding> 
    </bindings> 
    <client> 
     <endpoint address="https://dev-wcf.localhost/JP_WCF.svc" 
      binding="customBinding" bindingConfiguration="CustomBinding_IJP_WCF" 
      contract="JP_WCFService.IJP_WCF" name="CustomBinding_IJP_WCF" /> 
    </client> 
</system.serviceModel> 
+0

Tôi đang tự hỏi, làm thế nào bạn phát hiện rằng tiếp tục dòng sau khi một ngoại lệ xảy ra? –

+0

Ngoài ra, triển khai cho 'uploadStreamWithProgress' là gì? –

Trả lời

2

Khách hàng của bạn có kênh song công không? Nếu vậy, sau đó nó là khá thẳng về phía trước để gọi lại trên hợp đồng khách hàng để gửi thông tin khi tập tin được tải lên.

Nếu không, thì một cách tiếp cận tốt ở đây sẽ là truyền dữ liệu của bạn tới máy chủ theo khối bằng bộ đệm bộ nhớ. Có một vài ví dụ hay mà tôi đã đặt bên dưới.

Ý chính là bạn chia tệp thành các phần trên máy khách và gửi nó từng đoạn một đến máy chủ. Nếu bất kỳ đoạn nào không thành công, sau đó nó có thể thử lại đoạn đó, hoặc thất bại một cách duyên dáng mà không gửi thêm bất kỳ dữ liệu nào.

Các tham chiếu này sử dụng lớp học StreamWithProgress để xử lý logic này trên ứng dụng khách. Hi vọng điêu nay co ich.

Code Project reference

Simple implementation using StreamWithProgress class

3

Nếu bạn lo ngại về hiệu suất của cuộc gọi này, bạn luôn có thể thực hiện cuộc gọi máy chủ để kiểm tra tính hợp lệ của này tải lên trước khi phát trực tuyến. Bằng cách đó, bạn có thể tránh phát trực tiếp tệp nếu có sự cố và tránh bất kỳ trạng thái ngoại lệ nào trong ứng dụng của bạn (cũng tốn kém).

Vì vậy, bạn sẽ làm cho chuyến đi tương đối nhanh chóng đến máy chủ để xác nhận những thứ như

  1. vị trí hồ sơ hợp lệ
  2. quyền ghi vào vị trí đó
  3. kích thước của tập tin là hợp lệ
  4. bất kỳ các quy tắc kinh doanh có liên quan

Sau đó, bạn có thể thực hiện cuộc gọi mà không cần cố gắng quản lý luồng ứng dụng sử dụng ngoại lệ. Hãy nhớ rằng: Trường hợp ngoại lệ phải dành cho các trường hợp ngoại lệ. Bằng cách này, nếu ứng dụng của bạn làm tăng ngoại lệ, điều đó có nghĩa là có điều gì đó rất bất thường xảy ra và tốc độ nhúng là ngon miệng hơn (vì trường hợp này về lý thuyết rất hiếm).

Các vấn đề liên quan