2009-07-06 6 views
21

Czy jest wbudowany sposób pobierania pliku do lokalnego katalogu przy użyciu protokołu HTTP?Jak mogę użyć msbuild do pobrania pliku?

Mogę wykonać polecenie wget lub napisać niestandardowe zadanie, ale chciałem się upewnić, że nie było istniejącego sposobu na wykonanie tego zadania.

Z góry dziękuję!

Odpowiedz

1

Oprócz zadania WebDownload w projekcie MSBuild Community Tasks pakiet MSBuild Extension (aktualna wersja: 4.x) ma klasę WebClient, której można użyć do pobrania pliku. Można pobrać rozszerzenie pakietu MSBuild tutaj:

Oto przykład z użyciem MSBuild Extension Pack 4, aby pobrać plik:

<Project ToolsVersion="4.0" DefaultTargets="Default" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
<PropertyGroup> 
    <TPath>$(MSBuildProjectDirectory)\..\MSBuild.ExtensionPack.tasks</TPath> 
    <TPath Condition="Exists('$(MSBuildProjectDirectory)\..\..\Common\MSBuild.ExtensionPack.tasks')">$(MSBuildProjectDirectory)\..\..\Common\MSBuild.ExtensionPack.tasks</TPath> 
</PropertyGroup> 
<Import Project="$(TPath)"/> 
<Target Name="Default"> 
    <!-- Download a File--> 
    <MSBuild.ExtensionPack.Web.WebClient TaskAction="DownloadFile" Url="http://hlstiw.bay.livefilestore.com/y1p7GhsJWeF4ig_Yb-8QXeA1bL0nY_MdOGaRQ3opRZS0YVvfshMfoZYe_cb1wSzPhx4nL_yidkG8Ji9msjRcTt0ew/Team%20Build%202008%20DeskSheet%202.0.pdf?download" FileName="C:\TFS Build 2008 DeskSheet.pdf"/> 
    <!-- Get the contents of a Url--> 
    <MSBuild.ExtensionPack.Web.WebClient TaskAction="OpenRead" Url="http://www.msbuildextensionpack.com"> 
     <Output TaskParameter="Data" PropertyName="Out"/> 
    </MSBuild.ExtensionPack.Web.WebClient> 
    <Message Text="$(Out)"/> 
</Target> 

Jak wymienione w innej odpowiedzi, WebClient nie wydaje się mieć możliwości pobierania z bezpiecznego (zabezpieczenie hasłem ed) serwer WWW.

10

Jeśli próbujesz pobrać plik wymagający uwierzytelnienia (np. TFS Web lub serwer IIS dołączony do domeny), ani MSBuild Extension Pack ani MSBuild Community Tasks nie wydają się mieć możliwości nazwa użytkownika lub hasło do serwera HTTP. W tym przypadku zakończyłem pisanie niestandardowego zadania MSBuild. Oto co zrobiłem.

Postępowałem zgodnie z radą użytkownika przepełnienia stosu Doug, w jego odpowiedzi na Download a file which requires authentication using vb.net/c#?, w której sugeruje kod do dodania do metody napisanej przez Toma Archera na stronie internetowej Code Guru.

Więc użyłem MS Visual Studio 2010, aby utworzyć nowy C# projekt z poniższego kodu, aby utworzyć cel MSBuild nazwie Wget (pokazany pełny kod źródłowy):

// Include references to the following frameworks in your solution: 
// - Microsoft.Build.Framework 
// - Microsoft.Build.Utilities.v4.0 
// - System 
// - System.Net 

using System; 
using System.Net; 
using System.IO; 

using Microsoft.Build.Framework; 
using Microsoft.Build.Utilities; 

namespace Wget 
{ 
    public class Wget: Task 
    { 
     [Required] 
     public String Address // HTTP address to access 
     { get; set; } 

     [Required] 
     public String LocalFilename // Local file to which the downloaded page will be saved 
     { get; set; } 

     public String Username // Credential for HTTP authentication 
     { get; set; } 

     public String Password // Credential for HTTP authentication 
     { get; set; } 

     public override bool Execute() 
     { 
      int read = DownloadFile(Address, LocalFilename, Username, Password); 

      Console.WriteLine("{0} bytes written", read); 

      return true; 
     } 

     public static int DownloadFile(String remoteFilename, String localFilename, String httpUsername, String httpPassword) 
     { 
      // Function will return the number of bytes processed 
      // to the caller. Initialize to 0 here. 
      int bytesProcessed = 0; 

      // Assign values to these objects here so that they can 
      // be referenced in the finally block 
      Stream remoteStream = null; 
      Stream localStream = null; 
      WebResponse response = null; 

      // Use a try/catch/finally block as both the WebRequest and Stream 
      // classes throw exceptions upon error 
      try 
      { 
       // Create a request for the specified remote file name 
       WebRequest request = WebRequest.Create(remoteFilename); 
       if (request != null) 
       { 
        // If a username or password have been given, use them 
        if (httpUsername.Length > 0 || httpPassword.Length > 0) 
        { 
         string username = httpUsername; 
         string password = httpPassword; 
         request.Credentials = new System.Net.NetworkCredential(username, password); 
        } 

        // Send the request to the server and retrieve the 
        // WebResponse object 
        response = request.GetResponse(); 
        if (response != null) 
        { 
         // Once the WebResponse object has been retrieved, 
         // get the stream object associated with the response's data 
         remoteStream = response.GetResponseStream(); 

         // Create the local file 
         localStream = File.Create(localFilename); 

         // Allocate a 1k buffer 
         byte[] buffer = new byte[1024]; 
         int bytesRead; 

         // Simple do/while loop to read from stream until 
         // no bytes are returned 
         do 
         { 
          // Read data (up to 1k) from the stream 
          bytesRead = remoteStream.Read(buffer, 0, buffer.Length); 

          // Write the data to the local file 
          localStream.Write(buffer, 0, bytesRead); 

          // Increment total bytes processed 
          bytesProcessed += bytesRead; 
         } while (bytesRead > 0); 
        } 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
      finally 
      { 
       // Close the response and streams objects here 
       // to make sure they're closed even if an exception 
       // is thrown at some point 
       if (response != null) response.Close(); 
       if (remoteStream != null) remoteStream.Close(); 
       if (localStream != null) localStream.Close(); 
      } 

      // Return total bytes processed to caller. 
      return bytesProcessed; 
     } 
    } 
} 

Mając to na miejscu, mogę dodać następujące zadania do mojego projektu MSBuild:

<!-- Get the contents of a Url--> 
<Wget 
    Address="http://mywebserver.com/securepage" 
    LocalFilename="mydownloadedfile.html" 
    Username="myusername" 
    Password="mypassword"> 
</Wget> 

zadaniem Wget pobierze stronę podawane przez mywebserver.com i zapisuje je do pliku w bieżącym katalogu roboczym jako mydownloadedfile.html, używając nazwy użytkownika „myusername” i hasło "moje hasło".

Jednakże, aby użyć niestandardowego zadania Wget MSBuild, muszę powiedzieć programowi MSBuild, gdzie znaleźć plik zespołu Wget (.dll). Odbywa się to z elementem msbuild za:

<!-- Import your custom MSBuild task --> 
<UsingTask AssemblyFile="MyCustomMSBuildTasks\Wget\bin\Release\Wget.dll" TaskName="Wget" /> 

Jeśli chcesz uzyskać fantazyjny, można nawet mieć swój projekt MSBuild zbudować Wget zanim to się nazywa. Aby to zrobić, zbudować rozwiązanie zadania <MSBuild Projects> i zaimportować go z zadaniem <UsingTaks AssemblyFile>, coś takiego:

<!-- Build the custom MSBuild target solution--> 
<MSBuild Projects="MyCustomMSBuildTasks\CustomBuildTasks.sln" Properties="Configuration=Release" /> 

<!-- Import your custom MSBuild task --> 
<UsingTask AssemblyFile="MyCustomMSBuildTasks\Wget\bin\Release\Wget.dll" TaskName="Wget" /> 

<!-- Get the contents of a Url--> 
<Wget 
    Address="http://mywebserver.com/securepage" 
    LocalFilename="mydownloadedfile.html" 
    Username="myusername" 
    Password="mypassword"> 
</Wget> 

Jeśli nigdy nie stworzył zwyczaj cel MSBuild wcześniej, nie jest to zbyt trudne - raz znasz podstawy.Spójrz na powyższy kod C#, zapoznaj się z oficjalną dokumentacją MSDN i wyszukaj więcej w Internecie. Dobrym miejscem na rozpoczęcie jest:

+0

WebTownload społecznościowej obsługuje teraz uwierzytelnianie. – rasjani

25

W MSBuild 4.0 można używać wbudowanych zadań, aby uniknąć konieczności kompilacji i wdrożyć zadanie niestandardowe w oddzielnym zespole.

<UsingTask TaskName="DownloadFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> 
    <ParameterGroup> 
     <Address ParameterType="System.String" Required="true"/> 
     <FileName ParameterType="System.String" Required="true" /> 
    </ParameterGroup> 
    <Task> 
     <Reference Include="System" /> 
     <Code Type="Fragment" Language="cs"> 
     <![CDATA[ 
      new System.Net.WebClient().DownloadFile(Address, FileName); 
     ]]> 
     </Code> 
    </Task> 
    </UsingTask> 

    <Target Name="DownloadSomething"> 
    <DownloadFile Address="http://somewebsite/remotefile" FileName="localfilepath" /> 
    </Target> 
+1

Kiedy po raz pierwszy przeczytałem, nie było oczywiste, gdzie umieścić te dwa elementy. Dodałem powyżej zawierający moje pliki projektu i umieściłem w . –

+0

Niestety, to nie działa z podstawową wersją MSBuilda dotnet. – sakra