Come cancellare il download di file di grandi dimensioni ma ancora ottenere l’origine della pagina in C #?

Sto lavorando in C # su un programma per elencare tutte le risorse del corso per un MOOC (es. Coursera). Non voglio scaricare il contenuto, ma solo ottenere un elenco di tutte le risorse (es. Pdf, video, file di testo, file di esempio, ecc.) Che sono resi disponibili per il corso.

Il mio problema sta nell’analizzare il codice html (che attualmente utilizza HtmlAgilityPack) senza scaricare tutto il contenuto.

Ad esempio, se vai a questo video introduttivo per un corso bancario su Coursera e verifica la fonte (F12 in Chrome per gli Strumenti per sviluppatori), puoi vedere il sorgente della pagina. Posso interrompere il download del video che si avvia automaticamente, ma continua a vedere la fonte.

Come posso ottenere la fonte in C # senza scaricare tutto il contenuto? Ho cercato nelle intestazioni HttpWebRequest (problema: timeout) e DownloadDataAsync con Annulla (problema: l’object Risultato completato non è valido quando si annulla la richiesta asincrona). Ho anche provato vari caricamenti da HtmlAgilityPack ma senza successo.

Tempo scaduto:

HttpWebRequest postRequest = (HttpWebRequest)WebRequest.Create(url); postRequest.Timeout = TIMEOUT * 1000000; //Really long postRequest.Referer = "https://www.coursera.org"; if (headers != null) { //headers here } //Deal with cookies if (cookie != null) { cookieJar.Add(cookie); } postRequest.CookieContainer = cookiejar; postRequest.Method = "GET"; postRequest.AllowAutoRedirect = allowRedirect; postRequest.ServicePoint.Expect100Continue = true; HttpWebResponse postResponse = (HttpWebResponse)postRequest.GetResponse(); 

Qualche consiglio su come procedere?

Ci sono almeno due modi per fare ciò che stai chiedendo. Il primo è usare un intervallo get. Cioè, specifica l’intervallo del file che vuoi leggere. Lo fai chiamando AddRange su HttpWebRequest . Quindi se vuoi, per esempio, i primi 10 kilobyte del file, scrivi:

 request.AddRange(-10240); 

Leggi attentamente cosa dice la documentazione sul significato di quel parametro. Se è negativo, specifica il punto finale dell’intervallo. Ci sono anche altri sovraccarichi di AddRange cui potresti essere interessato.

Tuttavia, non tutti i server supportano l’intervallo. Se ciò non funziona, dovrai farlo in un altro modo.

Quello che puoi fare è chiamare GetResponse e quindi iniziare a leggere i dati. Una volta letti tutti i dati che vuoi, puoi interrompere la lettura e chiudere lo stream. Ho modificato leggermente il tuo campione per mostrare cosa intendo.

 string url = "https://www.coursera.org/course/money"; HttpWebRequest postRequest = (HttpWebRequest)WebRequest.Create(url); postRequest.Method = "GET"; postRequest.AllowAutoRedirect = true; //allowRedirect; postRequest.ServicePoint.Expect100Continue = true; HttpWebResponse postResponse = (HttpWebResponse) postRequest.GetResponse(); int maxBytes = 1024*1024; int totalBytesRead = 0; var buffer = new byte[maxBytes]; using (var s = postResponse.GetResponseStream()) { int bytesRead; // read up to `maxBytes` bytes from the response while (totalBytesRead < maxBytes && (bytesRead = s.Read(buffer, 0, maxBytes)) != 0) { // Here you can save the bytes read to a persistent buffer, // or write them to a file. Console.WriteLine("{0:N0} bytes read", bytesRead); totalBytesRead += bytesRead; } } Console.WriteLine("total bytes read = {0:N0}", totalBytesRead); 

Detto questo, ho eseguito questo esempio e scaricato circa 6 kilobyte e fermato. Non so perché hai problemi con timeout o troppi dati.

Si noti che a volte cercando di chiudere il stream prima che l'intera risposta venga letta, il programma si bloccherà. Non sono sicuro del perché ciò avvenga e non riesco a spiegare perché a volte capita. Ma puoi risolverlo chiamando request.Abort prima di chiudere lo stream. Questo è:

 using (var s = postResponse.GetResponseStream()) { // do stuff here // abort the request before continuing postRequest.Abort(); }