Передача файлов через WCF - PullRequest
2 голосов
/ 17 марта 2012

Я немного новичок в WCF, поэтому я был бы очень признателен, если бы вы могли ответить как можно более подробно :) У меня есть библиотека служб WCF и приложение WPF (кто является клиентом). желаемый результат - это приложение, которое позволит совместно использовать файлы между подключенными клиентами. Я создаю действительно базовую библиотеку служб WCF одним методом:

[ServiceContract]
public interface IFileService
{
    [OperationContract]
    byte[] GetFile(string fullPath);
}

И реализовал этот метод так:

public class FileService : IFileService
{
    public byte[] GetFile(string fullPath)
    {
        return System.IO.File.ReadAllBytes(fullPath);
    }
}

Это файл App.config в клиентском проекте WPF:

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WSHttpBinding_IFileService" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="false" />
                <security mode="Message">
                    <transport clientCredentialType="Windows" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true"
                        algorithmSuite="Default" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:9355/TankusFileTransferService/Service/"
            binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IFileService"
            contract="TankusFileService.IFileService" name="WSHttpBinding_IFileService">
            <identity>
                <userPrincipalName value="GIL-LAPTOP\Gil" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

А это код из главного окна WPF приложения:

public partial class MainWindow : Window
{

    ServiceHost sh;
    TankusFileService.FileServiceClient fsc;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void btn_Connect_Click(object sender, RoutedEventArgs e)
    {
        Uri uri = new Uri("http://127.0.0.1:1234/");
        sh = new ServiceHost(typeof(TankusFileTransferService.FileService), uri);
        sh.Open();
        lbl_Listener.Content = sh.Description.Endpoints[0].Address.ToString();
    }

    private void btn_Disconnect_Click(object sender, RoutedEventArgs e)
    {
        sh.Close();
        lbl_Listener.Content = string.Empty;
    }

    private void btn_GetFile_Click(object sender, RoutedEventArgs e)
    {
        fsc = new TankusFileService.FileServiceClient();
        fsc.Endpoint.Address = new EndpointAddress("http://127.0.0.1:1234/");
        fsc.Endpoint.Binding = new BasicHttpBinding();
        byte[] bytes = fsc.GetFile(@"D:\mika.txt");
        System.IO.File.WriteAllBytes(@"D:\mika_new.txt", bytes);
    }
}

После того, как я нажму кнопку подключения и инициализирую объект ServiceHost, чтобы он мог начать прослушивание, я нажимаю кнопку getFile. когда вызывается функция GetFile (), она генерирует исключение TimeoutException. Почему это? я даже на правильном пути для выполнения моей разыскиваемой заявки? Спасибо :)

Ответы [ 2 ]

2 голосов
/ 17 марта 2012

Вы, вероятно, получаете TimeoutException , поскольку для отправки файла требуется больше времени, чем разрешено вашей службой.

В вашем файле конфигурации для сервера и клиента обязательночтобы увеличить receiveTimeout и sendTimeout .

Вы также можете столкнуться с ограничениями размера, так как WCF настраивает максимальный размер сообщения, и файл будет считаться частью сообщения.,Посмотрите на maxBufferPoolSize , maxReceivedMessageSize и членов ниже

<readerQuotas 
     maxDepth="32" maxStringContentLength="8192" 
     maxArrayLength="16384" maxBytesPerRead="4096" 
     maxNameTableCharCount="16384" />
0 голосов
/ 18 марта 2012

Синхронный запрос веб-службы - не лучший способ передачи файлов.Даже если это работает, если вам нужно масштабировать конечную точку для обработки одновременных запросов, вы быстро столкнетесь с проблемами.Загружая файлы в конечные точки службы, вы ставите под угрозу доступность конечной точки.

Лучшее решение - приложение WPF записывает поток файлов на диск (или в базу данных, на ftp-сервер или в очередь), а затем отправляет быстрое одностороннее командное сообщение на сервер, который затем отправляется и захватывает файл.

Это значительно более масштабируемо и приведет к гораздо меньшему количеству исключений типа доступности.

ОБНОВЛЕНИЕ

По моему опыту, когда вы загружаете большие файлы в конечные точки веб-службы, вы можете столкнуться с проблемами доступности, особенно при наличии значительного параллелизма.Вы можете планировать эти вещи, если знаете, какие у вас верхние границы (размеры файлов, одновременные соединения и т. Д.), И вы можете формализовать это как соглашение об уровне обслуживания, но характер того, что вы пытаетесь сделать (одноранговыйравный) по определению является нестабильной средой, в которой такое планирование будет затруднено.

Тем не менее, тот факт, что ваше требование относится к P2P, означает, что в идеале не должно быть централизованной среды для реализации предложенного мной шаблона обмена сообщениями типа «сохраняй и получай».

Хранение BLOB-объектов Windows Azure является примером того, как этого можно достичь.

...