2009-07-06 46 views
21

是否有內置的方式使用HTTP將文件下載到本地目錄?如何使用msbuild下載文件?

我可以掏出wget或編寫自定義任務,但我想確保沒有現成的方法來完成此任務。

在此先感謝!

回答

1

除了MSBuild社區任務項目中的WebDownload任務,MSBuild擴展包(當前版本:4.x)還有一個WebClient類,可用於下載文件。您可以在這裏下載的MSBuild擴展包:

下面是使用MSBuild擴展包4,下載一個文件的例子:

<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> 

由於在不同的答案中提到,WebClient似乎沒有能力從安全(密碼保護編輯)網絡服務器。

10

如果您嘗試下載需要身份驗證的文件(例如TFS Web或連接到域的IIS服務器),則MSBuild擴展包和MSBuild社區任務似乎都無法提供用戶名或密碼到HTTP服務器。在這種情況下,我最終編寫了一個自定義的MSBuild任務。這就是我所做的。

我遵循堆棧溢出用戶Doug的建議,在他的回答爲Download a file which requires authentication using vb.net/c#?,其中他建議一些代碼添加到湯姆阿徹在代碼大師網站上寫的方法。

所以我用微軟的Visual Studio 2010中創建下面的代碼創建一個名爲Wget的一個MSBuild目標一個新的C#項目(顯示完整的源代碼):

// 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; 
     } 
    } 
} 

隨着到位,我可以添加以下任務到我的MSBuild項目:

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

wget的任務下載由mywebserver.com服務的頁面,並將其保存到當前工作目錄mydownloadedfile.html文件,使用用戶名「名爲myusername」和密碼「我的密碼」。

但是,爲了使用自定義Wget MSBuild任務,我必須告訴MSBuild在哪裏可以找到Wget程序集文件(.dll)。這是用的MSBuild的元素來完成的:

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

如果你想獲得幻想,你甚至可以有你的MSBuild項目建設Wget的,它被稱爲前。要做到這一點,建立與<MSBuild Projects>任務的解決方案,並與<UsingTaks AssemblyFile>任務導入,這樣的事情:

<!-- 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> 

如果你從來沒有之前創建一個自定義的MSBuild目標,這不是太困難的 - 一次你知道基礎知識。看看上面的C#代碼,看看官方的MSDN文檔,並在網上搜索更多的例子。一個良好的開始是:

+0

communitytask的WebDownload現在支持身份驗證。 – rasjani 2016-12-20 12:59:24

25

在MSBuild的4.0,你可以使用內聯任務,以避免需要編譯和在單獨的程序部署自定義任務。

<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

當我第一次閱讀這個內容時,並不清楚在哪裏放置這兩個元素。我在包含我的項目文件的上添加了,並將放入中。 – 2015-07-02 18:59:00