سؤال

لقد أمضيت معظم يومي في محاولة لمعرفة سبب عدم نجاح هذا. لدي خدمة WCF التي تدفق كائنًا إلى العميل. من المفترض أن يكتب العميل الملف على قرصه. لكن عندما أتصل stream.Read(buffer, 0, bufferLength) يعود دائمًا 0. إليك الرمز الخاص بي:

namespace StreamServiceNS
{
    [ServiceContract]
    public interface IStreamService
    {
        [OperationContract]
        Stream downloadStreamFile();
    }
}
class StreamService : IStreamService
{
    public Stream downloadStreamFile()
    {
        ISSSteamFile sFile = getStreamFile();
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        bf.Serialize(stream, sFile);
        return stream;
    }
}

ملف تكوين الخدمة:

<system.serviceModel>
<services>
  <service name="StreamServiceNS.StreamService">
    <endpoint address="stream" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IStreamService"
              name="BasicHttpEndpoint_IStreamService" contract="SWUpdaterService.ISWUService" />
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding_IStreamService" transferMode="StreamedResponse" 
             maxReceivedMessageSize="209715200"></binding>
  </basicHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceThrottling maxConcurrentCalls ="100" maxConcurrentSessions="400"/>
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

عميل:

TestApp.StreamServiceRef.StreamServiceClient client = new StreamServiceRef.StreamServiceClient();
        try
        {
            Stream stream = client.downloadStreamFile();
            int bufferLength = 8 * 1024;
            byte[] buffer = new byte[bufferLength];

            FileStream fs = new FileStream(@"C:\test\testFile.exe", FileMode.Create, FileAccess.Write);
            int bytesRead;
            while ((bytesRead = stream.Read(buffer, 0, bufferLength)) > 0)
            {
                fs.Write(buffer, 0, bytesRead);
            }
            stream.Close();
            fs.Close();
        }
        catch (Exception e) { Console.WriteLine("Error: " + e.Message); }

app.config العميل:

    <system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpEndpoint_IStreamService" maxReceivedMessageSize="209715200" transferMode="StreamedResponse">
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://[server]/StreamServices/streamservice.svc/stream"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpEndpoint_IStreamService"
            contract="StreamServiceRef.IStreamService" name="BasicHttpEndpoint_IStreamService" />
    </client>
    </system.serviceModel>

(تم قص بعض التعليمات البرمجية للإيجاز)

لقد قرأت كل ما يمكنني العثور عليه في عمل خدمات دفق WCF ، ولا يبدو رمزتي مختلفًا عن برامجهم. يمكنني استبدال البث بالتخزين المؤقت وإرسال كائن بهذه الطريقة بشكل جيد ، لكن عندما أحاول البث ، يرى العميل دائمًا أن الدفق "فارغ". ال testFile.exe يتم إنشاء ، ولكن حجمه هو 0 كيلو بايت.

ماذا ينقصني؟


تحديث
HRM. حسنًا ، لا يمكنني تصحيحه لأنه عندما أحاول أن يخبرني أن عميل اختبار WCF لا يدعم التدفقات. لكنني أعلم أن شيئًا ما يجعله عبر الدفق لأنني إذا لم أضع الحلقة ، ولدي فقط Fs.write (...) ، فسوف يكتب 8 كيلو بايت بمجرد إغلاق الدفق. لذلك هناك شيء ما هو الوصول.

نظرت إلى رسالتك وأضفت:

[MessageContract]
public class FileDownloadMessage
{
    [MessageBodyMember(Order = 1)]
    public MemoryStream FileByteStream;
}

لخدمتي istreamservice. و downloadStreamFile() الآن يعيد أ FileDownloadMessage هدف.

ولكن بعد تحديث مرجع الخدمة على موكلي ، يعتقد downloadStreamFile() إرجاع أ TestApp.StreamServiceRef.MemoryStream هدف.
كما أنشأ أ downloadStreamFileRequest() الفصل ، الذي لم أقم به وليس لدي أي فكرة من أين يأتي.

هل كانت مفيدة؟

المحلول

بادئ ذي بدء ، هل أنت قادر على تصحيح الخدمة ومعرفة ما إذا كان الدفق يحتوي على أي بيانات على هذا الجانب قبل إرسالها إلى العميل؟

أنا أعيد دفق من خدمة WCF الخاصة بي أيضًا. لقد واجهت مشكلة في ذلك أيضًا ، وإن لم يكن نفس المشكلة. نأمل أن يساعد الحل الذي وجدته. لقد وجدت الحل هنا. يتم التعامل مع هذا الحل مع تحميل دفق ، لكن التنفيذ في خدمة التنزيل الخاصة بي يعمل بشكل جيد.
سؤالي/الحل هنا (إجابتي الخاصة هي التي يجب أن تنظر إليها ، وليس الإجابة المقبولة لأن ذلك خاص بـ Ajax)

تحرير: الاختلافات الأساسية هي أنني قمت بلف دفق بلدي في MessageContract حيث حددت الدفق كعضو الوحيد في الرسالة وسمة ترتيب BasichTTP "ترتيب" "دفق". أنا جديد على WCF ، لذلك لا يمكنني التأكد من أن هذا سيساعد ، لكنني آمل أن يكون كذلك!

تحرير 2: لن أستخدم مرجع الخدمة. يمكنك تشغيل (من موجه CMD) 'svcutil.exe [mex url]' للحصول على ملف تكوين وملف .cs الذي قد يكون أكثر دقة مما تحصل عليه من مرجع الخدمة. ليس لدي حتى مرجع خدمة في مشروعي وهو يعمل بشكل جيد. فقط أضف ملف .cs الذي تم إنشاؤه إلى مشروعك وإضافة عبارة "استخدام" لذلك. أيضًا ، يمكنك إضافة إعدادات التكوين إلى ملفك أو ملف تكوين الويب الخاص بك على العميل. يتم إنشاء هذه الملفات التي تم إنشاؤها في الدليل الذي تقوم بتشغيل أمر SVCUTIL في.

ال DownloadStreamFileRequest الفصل هو مجرد كائن طلب ينقله العميل إلى base.Channel عند إجراء المكالمة إلى الخدمة. في الكود أدناه ، يطلق عليه GetExportedFileRequest

في ملف .cs الذي تم إنشاؤه ، لدي الطريقة التالية التي تعود System.IO.MemoryStreamويحصل على هذا الدفق من FileDownloadMessage هدف:

public System.IO.MemoryStream GetExportedFile()
{
    GetExportedFileRequest inValue = new GetExportedFileRequest();
    FileDownloadMessage retVal = ((IDailyBillingParser)(this)).GetExportedFile( inValue );
    return retVal.FileByteStream;
}

نصائح أخرى

واجهت أيضًا هذه المشكلة وما الذي نجح بالنسبة لي هو تحديد موقع الدفق إلى 0 قبل إرساله إلى العميل.

هل أي سبب تريد استخدامه "ثنائي التكافؤ"؟ إذا كان لا ، يمكنك العودة دفق من WCF مثل هذا

إرجاع FileStream جديد (@"d: yourfilename.txt" ، filemode.open ، fileAccess.Read)

في حال كان أي شخص يبحث هنا ، فإن خطأي كان يعيد filestream بدلاً من دفق من خدمة WCF الخاصة بي - هذا يعيد دائمًا دفقًا فارغًا. تغيير نوع الإرجاع إلى دفق حل مشكلتي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top