net - webclient c#
Descarga de mĂșltiples archivos WebClient (2)
Intento descargar varios archivos pero no funciona como esperaba. ¿Puede alguien decirme qué pasa con este guión, porque he probado muchas cosas y ya no sé qué hacer?
public static void DownloadFile(string url)
{
WebClient client = new WebClient();
var name = url.Substring(url.LastIndexOf(''/'')).Remove(0, 1);
foreach (var item in urls)
{
client.DownloadFile(item, "C://" + name);
}
}
private void btnGo_Click(object sender, EventArgs e)
{
urls.Add("url1");
urls.Add("url2");
urls.Add("url3");
Parallel.ForEach(urls,
new ParallelOptions { MaxDegreeOfParallelism = 10 },
DownloadFile);
}
using (var sr = new StreamReader(HttpWebRequest.Create(url).GetResponse().GetResponseStream()))
{
using (var sw = new StreamWriter(url.Substring(url.LastIndexOf(''/''))))
{
sw.Write(sr.ReadToEnd());
}
}
Está descargando todos los archivos al mismo archivo en su código de DownloadFile, que asume que una sola llamada a esta función descarga todos los archivos.
Correcciones:
Opción 1: No use Parallel.ForEach
y simplemente llame a DownloadFile una vez. Especifique nombres de archivo únicos para cada descarga. Es decir, al tomar parte de Url que está descargando o simplemente utilizando nombres de archivo aleatorios / temporales.
Algo como esto (suponiendo que las URL son algún tipo de IEnumerable<string>
)
foreach (var item in urls)
{
var name = item.Substring(item.LastIndexOf(''/'')).Remove(0, 1);
client.DownloadFile(item, "C://" + name);
}
Opción 2: Use Parallel.ForEach
pero cambie el código DownloadFile para descargar solo un archivo:
public static void DownloadFile(string url)
{
WebClient client = new WebClient();
var name = url.Substring(url.LastIndexOf(''/'')).Remove(0, 1);
client.DownloadFile(url, "C://" + name);
}
Yo usaría una System.Net.HttpWebRequest
lugar.
Así es como se vería el código:
private List<string> urls = new List<string>();
private void btnGo_Click(object sender, EventArgs e)
{
urls.Add("http://199.91.152.106/ua0p3fbc5nlg/gg2w2fq4ljc1nnd/MicroCraft_Beta.zip");
Parallel.ForEach(urls, new ParallelOptions { MaxDegreeOfParallelism = 10 }, DownloadFile);
}
public static void DownloadFile(string url)
{
var req = (HttpWebRequest)WebRequest.Create(url);
var name = url.Substring(url.LastIndexOf(''/'') + 1);
using (var res = (HttpWebResponse)req.GetResponse())
using (var resStream = res.GetResponseStream())
using (var fs = new FileStream("C://" + name, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Save to file
var buffer = new byte[8 * 1024]; // 8 KB buffer
int len; // Read count
while ((len = resStream.Read(buffer, 0, buffer.Length)) > 0)
fs.Write(buffer, 0, buffer.Length);
}
}
Porque la URL que me dijo en el comentario no utiliza una implementación adecuada del protocolo HTTP. Deberá agregar esto a su archivo de configuración para que funcione (ya sea App.config o Web.config, dependiendo de si es un sitio ASP.Net o una aplicación fuera de línea):
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
En cuanto a su problema con los nombres que colisionan, que dijo en su comentario, esto debería resolverse cambiando su var name = url.Substring(url.LastIndexOf(''/'')).Remove(0, 1);
en otra cosa.
Si desea tener un nombre de archivo incremental, puede usar esto:
// Inside your class:
private static int counter = 0;
// In your method:
var name = "file" + System.Threading.Interlocked.Increment(ref counter) + ".html";