2009-07-17 35 views
5

Tôi đã làm việc trên một WebCrawler được viết bằng C# bằng cách sử dụng System.Windows.Forms.WebBrowser. Tôi đang cố gắng tải xuống một tệp trên một trang web và lưu tệp đó trên máy cục bộ. Quan trọng hơn, tôi muốn điều này hoàn toàn tự động. Tải xuống tệp có thể được bắt đầu bằng cách nhấp vào nút gọi hàm javascript để kích hoạt tải xuống hiển thị hộp thoại “Bạn có muốn mở hoặc lưu tệp này không?”. Tôi chắc chắn không muốn được bấm bằng tay "Lưu dưới dạng" và nhập tên tệp.Tự động tải xuống bằng cách sử dụng WebBrowser mà không cần url

Tôi biết về các chức năng tải xuống của HttpWebRequest và WebClient, nhưng kể từ khi tải xuống được bắt đầu bằng javascript, giờ đây tôi đã biết URL của tệp. Fyi, javascript là một hàm doPostBack thay đổi một số giá trị và gửi một biểu mẫu.

Tôi đã cố gắng tập trung vào hộp thoại lưu dưới dạng từ WebBrowser để tự động hóa hộp thoại từ đó mà không cần nhiều thành công. Tôi biết có một cách để buộc tải xuống lưu thay vì yêu cầu lưu hoặc mở bằng cách thêm tiêu đề vào yêu cầu http, nhưng tôi không biết cách chỉ định tệp để tải xuống.

+0

Bạn có một giải pháp để cuối cùng của bạn vấn đề, làm thế nào để tải về các tập tin khi nó được tạo ra trên bay và bạn không thể xác định rằng nó là một tập tin tải về từ url? –

Trả lời

5

Tôi nghĩ bạn nên ngăn hộp thoại tải xuống hiển thị. Đây có thể là một cách để làm điều đó:

  • Các mã Javascript gây WebBrowser kiểm soát của bạn để điều hướng đến một URL cụ thể (những gì có thể gây ra các hộp thoại download xuất hiện)

  • Để ngăn chặn sự kiểm soát WebBrowser từ thực sự Điều hướng đến Url này, đính kèm trình xử lý sự kiện vào sự kiện Điều hướng. Trong sự kiện điều hướng của bạn, bạn phải phân tích nếu đây là hành động Điều hướng thực sự bạn muốn dừng lại (đây có phải là url tải xuống, có thể kiểm tra phần mở rộng tệp, phải có định dạng dễ nhận biết) . Sử dụng WebBrowserNavigatingEventArgs.Url để làm như vậy.

  • Nếu đây là Url đúng, hãy dừng Điều hướng bằng cách đặt thuộc tính WebBrowserNavigatingEventArgs.Cancel.

  • Tiếp tục tải xuống bản thân với HttpWebRequest hoặc WebClient lớp

Có một cái nhìn tại trang này để biết thêm về sự kiện này:
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.navigating.aspx

+1

Tôi đã thử nhận url bằng cách sử dụng HttpDebugger để xem yêu cầu và phản hồi http. Url chính xác giống nhau, một là yêu cầu GET, yêu cầu còn lại là yêu cầu POST. Tôi cũng vừa thử đề xuất của bạn mà không có may mắn. – Sharath

+0

Bạn có thể muốn sử dụng điều khiển WebBrowser để đến cuối cùng, ngay trước khi biểu mẫu được gửi và sau đó trích xuất đích POST của biểu mẫu bằng DOM (lấy tham chiếu đến nội dung tài liệu HTML và từ đó thực hiện theo cách của bạn hình thức). – Zyphrax

3

Một giải pháp tương tự có sẵn tại http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/d338a2c8-96df-4cb0-b8be-c5fbdd7c9202/?prof=required

Công việc này hoàn hảo nếu có URL trực tiếp bao gồm tải xuống tên tệp.

Nhưng đôi khi một số URL tạo tệp động. Vì vậy, URL không có tên tệp nhưng sau khi yêu cầu URL đó, một số trang web tạo tệp động và sau đó mở/lưu hộp thoại đến.

ví dụ: một số liên kết tạo tệp pdf khi đang di chuyển.

Cách xử lý loại URL như vậy?

1

Hãy xem bài viết Erika Chinchio trên http://www.codeproject.com/Tips/659004/Download-of-file-with-open-save-dialog-box

Tôi đã sử dụng thành công nó để tải các url pdf tạo động.

+2

Trong khi điều này về mặt lý thuyết có thể trả lời câu hỏi, [nó sẽ là thích hợp hơn] (// meta.stackoverflow.com/q/8259) để bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. –

1

Giả sử System.Windows.Forms.WebBrowswer được sử dụng để truy cập vào một trang được bảo vệ với một liên kết bảo vệ mà bạn muốn tải về:

Mã này lấy liên kết thực tế mà bạn muốn tải về bằng cách sử dụng web trình duyệt. Mã này sẽ cần phải được thay đổi cho hành động cụ thể của bạn. Phần quan trọng là trường này là documentLinkUrl sẽ được sử dụng bên dưới.

var documentLinkUrl = default(Uri); 
browser.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) => 
{ 
    var aspForm = browser.Document.Forms[0]; 
    var downloadLink = browser.Document.ActiveElement 
     .GetElementsByTagName("a").OfType<HtmlElement>() 
     .Where(atag => 
      atag.GetAttribute("href").Contains("DownloadAttachment.aspx")) 
     .First(); 

    var documentLinkString = downloadLink.GetAttribute("href"); 
    documentLinkUrl = new Uri(documentLinkString); 
} 
browser.Navigate(yourProtectedPage); 

Bây giờ trang được bảo vệ đã được điều hướng bởi trình duyệt web và liên kết tải xuống đã được mua, Mã này tải xuống liên kết.

private static async Task DownloadLinkAsync(Uri documentLinkUrl) 
{ 
    var cookieString = GetGlobalCookies(documentLinkUrl.AbsoluteUri); 
    var cookieContainer = new CookieContainer(); 
    using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer }) 
    using (var client = new HttpClient(handler) { BaseAddress = documentLinkUrl }) 
    { 
     cookieContainer.SetCookies(this.documentLinkUrl, cookieString); 
     var response = await client.GetAsync(documentLinkUrl); 
     if (response.IsSuccessStatusCode) 
     { 
      var responseAsString = await response.Content.ReadAsStreamAsync(); 
      // Response can be saved from Stream 

     } 
    } 
} 

Đoạn mã trên dựa vào phương pháp GetGlobalCookies từ Erika Chinchio có thể được tìm thấy trong các bài viết xuất sắc được cung cấp bởi @Pedro Leonardo (có sẵn here),

[System.Runtime.InteropServices.DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] 
static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, 
    System.Text.StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved); 

const int INTERNET_COOKIE_HTTPONLY = 0x00002000; 

private string GetGlobalCookies(string uri) 
{ 
    uint uiDataSize = 2048; 
    var sbCookieData = new System.Text.StringBuilder((int)uiDataSize); 
    if (InternetGetCookieEx(uri, null, sbCookieData, ref uiDataSize, 
      INTERNET_COOKIE_HTTPONLY, IntPtr.Zero) 
     && 
     sbCookieData.Length > 0) 
    { 
     return sbCookieData.ToString().Replace(";", ","); 
    } 
    return null; 
} 
Các vấn đề liên quan