[VB/C#] Pobieranie webclientem ZIPa z GitHuba

Witam

Zmagam się aktualnie z webclientem i pobieraniem asynchronicznym plików. Piszę aplikację w VB.NET i kod, który napisałem jest na pewno poprawny, ponieważ taką instalke Gimpa pobiera bez problemu i ładnie pokazuje postęp pobierania. Ale docelowo chciałem użyć tego kodu do pobierania ZIPa znajdującego się w Releases na GitHubie, lecz każda próba pobrania go kończy się od razu wywołaniem DownloadFileCompleted i pojawieniem się na dysk pliku ZIP o rozmiarze 0 bitów. Czy takie pobieranie z tego serwisu wiąże się z jakimiś ograniczeniami lub potrzebne są jakieś dodatkowe headery?

Proszę o pomoc, jest mi to bardzo potrzebne

Może to kwestia https’a? Jakieś przekierowanie? Ciężko powiedzieć bez konkretnego kodu.

1 polubienie

Dodatki dla Firefox nie wymagają jak podam pełny adres do pliku z ich nowszą wersją ale jak się to ma do VB/C#…

Dim client As WebClient = New WebClient()
AddHandler client.DownloadProgressChanged, AddressOf DownloadProgressChanged
AddHandler client.DownloadFileCompleted, AddressOf DownloadFileCompleted
client.DownloadFileAsync(New Uri("https://github.com/sciezka_do_repo_i_pliku.zip"), Application.StartupPath & "\plik.zip")

Jako linku do zipa używam linku podanego przez przeglądarkę, on jest na pewno poprawny, w przeglądarce zwraca on plik, jest on także podawany jako link do pobierania przez API GitHuba w JSONie

Debuguj żądanie http. Zarówno w swojej aplikacji jak i w przeglądarce, być może gh sprawdza/wymaga jakiś nagłówków w żądaniu.

A mógłbyś nakierować jak to zrobić?

Zobacz https://stackoverflow.com/questions/32223706/download-zipball-from-github-in-c-sharp
Prawdopodobnie musisz dodać user-agent (tak jak wspomniał @Fizyda)

Dodałem taką linijkę i bez zmian:
client.Headers(“User-Agent”) = “Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36”

Zainstaluj i uruchom Fiddler, po czym porównaj swoje żądanie z tym idącym z przeglądarki. Powinieneś dojść do przyczyny.

Nie wiem czy o to chodzi, ale zauważyłem to w tej aplikacji. Użycie aplikacji i przeglądarki przekierowuje na adres github-production-release-asset-… Żądanie z przeglądarki ma sekcję Client z User-Agent, a ta z aplikacji nie posiada User-Agenta mimo użycia:
client.Headers.Add(“User-Agent”, “Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36”)

Z przeglądarki:

Z aplikacji:

Po pierwsze zabierając się za pisanie tego typu aplikacji warto byłoby chociaż zaznajomić się z podstawami protokołu HTTP oraz w ogóle działania aplikacji sieciowych.

Kolejna sprawa, że warto byłoby w pierwszej kolejności zorientować się czy nie ma jakiś metod ułatwiających życie - w tym przypadku pobieranie repo. Może warto byłoby sprawdzić API GitHuba pod kątem potrzebnej funkcjonalności? Jestem w 100% pewny, że jakieś API GH udostępnia.

Trzecia rzecz, masz wywalony żółty komunikat, że odszyfrowywanie połączenia HTTPS jest wyłączone, więc nie wiem jakie dane ty chcesz odczytać … tutaj warto byłoby też zainteresować się czym jest HTTPS i jak mniej więcej działa.

Nie wiem po co @kowgli proponuje używać jakiegoś dodatkowego programu, zwłaszcza, że do czynienia mamy z HTTPS i nie każdy program do przechwytywania pakietów potrafi sobie z takim połączeniem poradzić. Nawet jeśli potrafi to trzeba umieć to jeszcze skonfigurować. Być może aplikacja jest spoko, nie wiem, nie używałem, ale zgaduję, że jest to coś podobnego do WireSharka. Jednak uważam, że jest cała masa prostszych sposobów na inspekcje rządań bez dodatkowego softu. W przypadku przeglądarki masz wbudowane narzędzia, a w przypadku własnego kodu masz coś takiego jak debugger i w ogóle możesz sobie robić z klientem co chcesz bo to Twój kod. Programy tego typu są potrzebne jedynie gdy analizujesz komunikację dla zamkniętej aplikacji, w tedy taka zabawa ma sens.
Wystarczyło 5 sekund by zorientować się jak działa pobieranie zipa z GH w przeglądarce i dojść do wniosku, że robisz to w zły sposób (o czym więcej później).


Jak byk widać, że adres który widnieje na stronie GH do downloadu jest później przekierowywany (302), a sam plik znajduje się pod innym adresem.

Wystarczyło też wpisać w google C# github zip download by znaleźć odpowiedzi na problem i od razu sugestię by wykorzystać API GH.
Jednak można to też zrobić bez API, wystarczy tylko użyć clienta który sam w razie przekierowania przejdzie pod inny, wskazany adres i pobierze plik. Tym razem wystarczyło wpisać w google .net webclient with 302 redirect by dowiedzieć się z pierwszego linku, że wystarczy użyć klasy HttpWebRequest z odpowiednią konfiguracją.

EDIT:
Tak mi się jeszcze przypomniało.
Do ustalenia tego czemu nie pobierasz pliku wystarczyło sprawdzić co Ci serwer odpowiada by znaleźć problem. Nie trzeba było nawet odpalać przeglądarki.

2 polubienia

Wszystko super tylko autor pisze w VB :stuck_out_tongue: Więc VB.NET github zip download

W przypadku .net nie ma znaczenia w czym pisze. Ja szukałem w C# bo znam C#, a składnia VB jest dla mnie co najmniej dziwna. Z każdego języka w którym pisze programista (w przypadku .net) kod jest najpierw kompilowany na wewnętrzny języka CIL, który jest uruchamiany w środowisku uruchomieniowym .net framework. W przypadku .net można powiedzieć że każdy jeden język to tylko syntax sugar. Po skompilowaniu środowisko uruchomieniowe nie wie w jakim języku kod został napisany.
Poza tym uważam, że więcej przykładów jest dla C# niż VB, a przełożyć jedno na drugie to moment, nawet nie trzeba znać składni. Wystarczy tylko idea rozwiązania problemu, a reszta jest w dokumentacji. Wielokrotnie przenosiłem przykładowe rozwiązanie problemu napisane w VB na C#, a VB w dalszym ciągu nie znam i nie chcę znać.

EDIT:
Zresztą sam problem pobierania zipa mógłby zostać rozwiązany nawet w PHP albo Java (jako przykład), bo tutaj problemem jest tylko brak koncepcji oraz tego w czym tkwi problem i jak go rozwiązać. Przynajmniej ja takie wrażenie odniosłem. A całość sprowadza się do tego, że autor nie wie nawet orientacyjnie, jak mniej więcej działa protokół HTTP.

1 polubienie

Próbuje z tym HttpWebRequest tak jak pokazują to w internecie, ale kod wysypuje się na trzeciej linijce z GetResponse, bez jakiegokolwiek błędu.

Dim req As HttpWebRequest = WebRequest.Create("link_do_zipa")
req.AllowAutoRedirect = True
Dim resp As HttpWebResponse = req.GetResponse()

Oraz przejrzałem ponownie API GitHuba i nie znalazłem nic co pozwoliło by mi na pobranie tego pliku, jedyne co mogę z niego wyciągnąć to browser_download_url, czyli nic innego jak link, którego używam od samego początku.

  1. Pokaż w takim razie jaki jest ten link, którego używasz. Może ja coś źle zrozumiałem ponieważ w dokumentacji API zwracany jest zupełnie inny link do downloadu archiwum niż ten pod przyciskiem na stronie GH.
  2. Co to znaczy, że kod wysypuje się? Jak się to objawia, bo zazwyczaj jest jakiś kod błędu albo informacja.
  3. Zakładam, że kod się nie wysypuje tylko ze względu na to, że pobierasz plik synchronicznie, powoduje to, że aplikacja Ci się na czas pobierania “zawiesza”.
  4. Pamiętaj, że w ten sposób pobierasz odpowiedź na żądanie, więc musisz sam sprawdzić co dostałeś i z odpowiedzi HTTP sam zapisać plik na dysku.

Widzę, że prawdopodobnie się nie zrozumieliśmy. Ja nie pobieram zipa z repozytorium tylko ZIPa, którego sam dodałem do kompilacji w zakładce releases. Co do błędu to tak jak napisałem kod przerywa wykonywanie na tej linijce co pokazałem oraz zamyka okno w którym jest ten kod. To nie jest zawieszenie głównego wątku bo to potrafię rozpoznać, okno zamyka się i pojawia się główne okno aplikacji (tamto okno do testów sztucznie dodałem do startu aplikacji by nie musieć niepotrzebnie klikać). Teraz zauważyłem że podczas tego wyrzucenia kodu w Outpucie pokazuje się “Exception thrown: ‘System.Net.WebException’ in System.dll”. I wiem, czytałem że później będę musiał samemu napisać kod do zapisu pliku tylko przestałem go pisać jak zauważyłem takie zachowanie programu.

No to to zmienia postać rzeczy. Źle zrozumiałem pierwszy post bo nigdy nie trzymałem zipów w repo i nigdy się z tym nie spotkałem. Wydaje mi się, że w takiej sytuacji bez API się nie obejdzie.

Bez kodu ciężko coś powiedzieć bo może po prostu okno się zamknęło bo kod się wykonał.

No to przechwyć wyjątek i zobacz messege wyjątku.

Dla świętego spokoju pokaż jeszcze link do downloadu, może być zmyślona nazwa usera repo i pliku, byleby był cały link z zachowanym jego formatem.

https://github.com/user/repozytorium/releases/download/nazwa_taga/plik_zip.zip

Nie wiem czemu ta linijka powoduje całkowite zamknięcie okna, ale to na bank nie moja wina. Dałem tą linijkę w Try…Catch i pobrałem komunikat: “Żądanie zostało przerwane: Nie można utworzyć bezpiecznego kanału SSL/TLS”. Spróbowałem zmienić w linku protokół na http, ale błąd się nie zmienił.

Błąd się nie zmieni bo github nie obsługuje http - zresztą już jak większość serwisów.

/releases/download/nazwa_taga/plik_zip.zip
To są wszystko nazwy katalogów w Twoim projekcie?
Link który podałeś, nie będzie prowadził do zawartości pliku lecz do strony na której GH będzie próbował wygenerować podgląd pliku. W ten sposób nie pobierzesz archiwum które jest plikiem binarnym. W ten sposób mógłbyś próbować zapisać plik tekstowy poprzez wyłuskanie z kodu html jego zawartości. W api masz od tego funkcje - w sensie od uzyskania linku do downloadu.

Prościej jest szukać rozwiązania z błędami po angielsku … musisz ustawić konfigurację dla połączeń szyfrowanych, pierwszy link z google: https://www.c-sharpcorner.com/forums/ssl-httpwebrequest-in-c-sharp-could-not-create-ssltls-secure-channel

Tutaj masz konkretne żądanie API by uzyskać link do downloadu: https://developer.github.com/v3/repos/contents/#get-contents
Download pliku powinien odbyć się w dwóch krokach:

  1. Wykorzystać API do pobrania download_url - możesz do tego raczej użyć klasy WebClient
  2. Przy pomocy powyższego adresu pobrać plik - prawdopodobnie pójdzie już przez WebClient bo powinien to być już link bezpośredni bez przekierowań, ale musisz to sprawdzić już sam
    Prawdopodobnie w przypadku klasy WebClient będziesz miał już skonfigurowane połączenie SSL/TLS.

To są wszystko nazwy katalogów w Twoim projekcie?

Nie to nie są katalogi w projekcie tylko bardziej podział projektu na githubie na zakładki.

https://github.com/Aris-t2/CustomCSSforFx - kod (/tree/nazwa_gałęzi - ukryte i widoczne po otwarciu jakiegoś pliku / katalogu)
https://github.com/Aris-t2/CustomCSSforFx/releases/tag/1.8.5 - wydanie jakiś tag
https://github.com/Aris-t2/CustomCSSforFx/releases/download/1.8.5/custom_css_for_fx_v1.8.5.1.zip - "generator podglądu pliku"
1 polubienie