Статьи

Резервное копирование данных приложения Windows Phone на сервер, как GoDaddy

Вот полное пошаговое руководство по созданию службы резервного копирования WCF для приложений Windows Phone.

Вы можете реализовать свой собственный хостинг с дешевым хостинг-сервером, таким как GoDaddy. Вы можете найти сделку на $ 5 / месяц. Лично я считаю более профессиональным сохранение данных вашего приложения на частном сервере или в облачном решении, а не ретрансляцию в SkyDrive.

Для этого необходимы две вещи:
A- Внедрение службы на вашем сервере.
B- Внедрение клиентского кода для отправки ваших данных.

Кроме того, вы можете скачать полное решение в конце статьи.

А) Сторона сервера

1- Давайте начнем с самой сложной части. После того, как вы найдете хост-сервер, который поддерживает платформу .NET 4.0, вы создаете приложение-службу WCF:

образ

2- Переименуйте файл IService1.cs в IFileUploader.cs.

3- Замените содержимое файла IFileUploader.cs следующим:

using System.Runtime.Serialization;
using System.ServiceModel;

namespace FileUploadService
{
    [ServiceContract]
    public interface IFileUploader
    {
        // Returns null when there is no error, otherwise it is the exception message.
        [OperationContract]
        string Upload(UploadFile uploadFile);
    }

    [DataContract]
    public class UploadFile
    {
        // Don't forget to set the variable FileUploadDirectoryWithReadWritePermission in your Web.config and set read/write permission in your web hosting.
        // RelativeDirectory should be in the form as /Path1/Path2/ or null for the root directory.
        [DataMember]
        public string RelativeDirectory { get; set; }

        [DataMember]
        public string FileName { get; set; }

        [DataMember]
        public byte[] Content { get; set; }
    }
}

Этот интерфейс содержит только метод Upload. Для загрузки требуется UploadFile, который содержит только 3 свойства: RelativeDirectory, FileName и Content.

4- Переименуйте файл Service1.svc в FileUploader.svc.

5- Заменить содержимое FileUploader.svc следующим:

using System;
using System.Configuration;
using System.IO;
using System.Web.Hosting;

namespace FileUploadService
{
    public class FileUploader : IFileUploader
    {
        #region IFileUploader Members

        public string Upload(UploadFile uploadFile)
        {
            string message = null;

            try
            {
                string path = HostingEnvironment.MapPath(string.Format("~/{0}",ConfigurationManager.AppSettings["FileUploadDirectoryWithReadWritePermission"]));

                if (path != null)
                {
                    if (uploadFile.RelativeDirectory != null && uploadFile.RelativeDirectory.StartsWith("/"))
                    {
                        path = string.Concat(path, uploadFile.RelativeDirectory);
                    }

                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }

                    if (!string.IsNullOrEmpty(uploadFile.FileName))
                    {
                        using (FileStream fileStream = File.Open(Path.Combine(path, uploadFile.FileName), FileMode.Create))
                        {
                            using (var binaryWriter = new BinaryWriter(fileStream))
                            {
                                binaryWriter.Write(uploadFile.Content);
                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                message = exception.Message;
            }

            return message;
        }

        #endregion
    }
}

6- Замените содержимое файла Web.config на:

<?xml version="1.0"?>

<configuration>

  <appSettings>
    <add key="FileUploadDirectoryWithReadWritePermission" value="/backup/" />
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <customErrors mode="Off" />
  </system.web>

  <system.serviceModel>

    <behaviors>
      <serviceBehaviors>
        <behavior name="FileUploadBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>
      <service behaviorConfiguration="FileUploadBehavior" name="FileUploadService.FileUploader">
        <endpoint address="" name="basicHttpStream" binding="basicHttpBinding"
                  bindingConfiguration="httpLargeMessageStream" contract="FileUploadService.IFileUploader" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

    <bindings>
      <basicHttpBinding>
        <binding receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"
                 name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
          <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
        </binding>
      </basicHttpBinding>
    </bindings>

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>

</configuration>

Этот файл имеет два важных раздела:

— Параметр FileUploadDirectoryWithReadWritePermission используется файлом FileUploader.svc и будет использоваться в вашей общей папке позже.

  <appSettings>
    <add key="FileUploadDirectoryWithReadWritePermission" value="/backup/" />
  </appSettings>

— Раздел о длине параметров услуги: здесь не нужно все понимать. Это просто работает как есть. Если вам интересно, я предлагаю вам прочитать документацию по MSDN.

<bindings>
      <basicHttpBinding>
        <binding receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"
                 name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
          <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
        </binding>
      </basicHttpBinding>
    </bindings>

7- Сервис готов к публикации. Щелкните правой кнопкой мыши проект FileUploadService и выберите «Опубликовать». В зависимости от вашего веб-хостинга, вам нужно установить информацию.

Для GoDaddy:

— Используйте метод FTP.

— Установите целевое местоположение. Для меня я использовал ftp://ftp.ultimatepokermanager.com/upm/ServerTest

— установить учетные данные 

образ

8. Самая сложная задача — настроить параметры приложения для службы WCF в службе хостинга. В GoDaddy это в IIS Management в разделе Инструменты. Вам необходимо проверить анонимный доступ и установить корень приложения.

Тест upm \ servertest указывает на http://www.ultimatepokermanager.com/upm/servertest

образ

8- Чтобы проверить, работает ли ваша служба, откройте браузер и введите адрес веб-службы. С моим веб-сервисом адрес:

http://www.ultimatepokermanager.com/upm/servertest/FileUploader.svc

Если вы видите что-то вроде следующего изображения, вы готовы!

образ

 

Б) Клиентская сторона

Я создал простое приложение, которое отправляет строку в файл на сервере.

образ

1- Создайте приложение для Windows Phone. Я предполагаю, что вы знаете, как сделать этот шаг.

2. Клиент службы WCF FileUploader необходимо добавить в проект. Щелкните правой кнопкой мыши по проекту Windows Phone и выберите «Добавить ссылку на службу».

образ

— Введите адрес вашего сервиса WCF. В этом примере это http://www.ultimatepokermanager.com/upm/servertest/FileUploader.svc 
— переименуйте пространство имен в FileUploader.

— Нажмите ОК.

3- Замените содержимое MainPage.xaml следующим:

<phone:PhoneApplicationPage x:Class="SendFileApp.MainPage"
                            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                            xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
                            xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
                            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                            mc:Ignorable="d"
                            d:DesignWidth="480"
                            d:DesignHeight="800"
                            FontFamily="{StaticResource PhoneFontFamilyNormal}"
                            FontSize="{StaticResource PhoneFontSizeNormal}"
                            Foreground="{StaticResource PhoneForegroundBrush}">

    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel Margin="12,17,0,28">

            <TextBlock Text="SEND FILE"
                       Style="{StaticResource PhoneTextNormalStyle}" />

            <TextBlock Text="dashboard"
                       Margin="9,-7,0,0"
                       Style="{StaticResource PhoneTextTitle1Style}" />

        </StackPanel>

        <StackPanel Grid.Row="1"
                    Margin="12,0,12,0">

            <TextBlock Margin="12,0,0,0"
                       Text="Content" />

            <TextBox Text="abcdefg"
                     x:Name="textBoxContent" />

            <TextBlock Margin="12,0,0,0"
                       Text="File name" />

            <TextBox Text="Sample.txt"
                     x:Name="textBoxFileName" />

            <Button Content="Send File"
                    Click="ButtonSendFile" />

            <Button Content="Download File"
                    Click="ButtonDownloadFile"
                    IsEnabled="False"
                    x:Name="buttonDownloadFile"/>

        </StackPanel>

    </Grid>

</phone:PhoneApplicationPage>

Этот контент использует только стандартные элементы управления.

4- Замените содержимое MainPage.xaml.cs на:

using System;
using System.Net;
using System.Text;
using System.Windows;
using SendFileApp.FileUploader;

namespace SendFileApp
{
    public partial class MainPage
    {
        #region Constants

        // For this sample, the uploaded file can be access from my public folder
        private const string PublicServer = "http://www.ultimatepokermanager.com/upm/ServerTest/backup";

        #endregion

        #region Fields

        private string _directory;

        #endregion

        #region Constructor

        public MainPage()
        {
            InitializeComponent();
        }

        #endregion

        #region Event Handlers

        private void ButtonSendFile(object sender, RoutedEventArgs e)
        {
            byte[] content = Encoding.UTF8.GetBytes(textBoxContent.Text);
            _directory = Guid.NewGuid().ToString();

            FileUploaderClient fileUploaderClient = new FileUploaderClient();
            fileUploaderClient.UploadCompleted += UploadCompleted;

            fileUploaderClient.UploadAsync(new UploadFile { RelativeDirectory = string.Format("/{0}", _directory), FileName = textBoxFileName.Text, Content = content });
        }

        private void UploadCompleted(object sender, UploadCompletedEventArgs uploadCompletedEventArgs)
        {
            buttonDownloadFile.IsEnabled = true;

            if (uploadCompletedEventArgs.Result == null)
            {
                MessageBox.Show("The file has been successfully uploaded.", "Success!", MessageBoxButton.OK);
            }
            else
            {
                MessageBox.Show(string.Format("An error occured:\n\n{0}", uploadCompletedEventArgs.Result), "Error", MessageBoxButton.OK);
            }
        }

        private void ButtonDownloadFile(object sender, RoutedEventArgs e)
        {
            WebClient webClient = new WebClient();
            webClient.DownloadStringCompleted += WebClientDownloadStringCompleted;

            webClient.DownloadStringAsync(new Uri(string.Format("{0}/{1}/{2}", PublicServer, _directory, textBoxFileName.Text)));
        }

        private void WebClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs downloadStringCompletedEventArgs)
        {
            if (downloadStringCompletedEventArgs.Error == null)
            {
                MessageBox.Show(string.Format("The content of your file is:\n\n{0}", downloadStringCompletedEventArgs.Result), "Success!", MessageBoxButton.OK);
            }
            else
            {
                MessageBox.Show(string.Format("An error occured:\n{0}", downloadStringCompletedEventArgs.Error), "Error", MessageBoxButton.OK);
            }
        }

        #endregion
    }
}

Интересная часть в предыдущем коде:

private void ButtonSendFile(object sender, RoutedEventArgs e)
{
    byte[] content = Encoding.UTF8.GetBytes(textBoxContent.Text);
    _directory = Guid.NewGuid().ToString();

    FileUploaderClient fileUploaderClient = new FileUploaderClient();
    fileUploaderClient.UploadCompleted += UploadCompleted;

    fileUploaderClient.UploadAsync(new UploadFile { RelativeDirectory = string.Format("/{0}", _directory), FileName = textBoxFileName.Text, Content = content });
}

Использование FileUploaderClient действительно просто:

1- Создайте экземпляр FileUploaderClient.

2- Прослушивание события UploadCompleted.

3- Загрузите файл асинхронно.

Обратите внимание, что для UploadFile нужны свойства RelativeDirectory (который начинается с «/»), FileName и Content в массиве байтов.

Пример адреса загруженного файла: http://www.ultimatepokermanager.com/upm/ServerTest/ backup /a5a8ae0b-50f0-4d16-90da-e83d6e1d30a3/Sample.txt . Вы можете увидеть каталог резервных копий, ранее установленный в файле Web.config.

В этом примере я сгенерировал GUID для имени каталога. Кроме того, загруженные файлы являются общедоступными, пока пользователь (или приложение) знает об имени каталога и имени файла. Если вы хотите добавить уровень конфиденциальности, вам просто нужно внедрить метод DownloadFile в ваш сервис. Это не должно быть сложно, если вы читаете код метода Upload.

Я гарантирую вам, что вы будете рады видеть, когда ваш веб-сервис работает!

Скачать пример проекта