Folgende Namespaces werden gebraucht:
PHP Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.Threading;
PHP Code:
System.Net.ServicePointManager.DefaultConnectionLimit = 1000;
Hier sind die zwei Klassen:
PHP Code:
class Download
{
private FileStream _file;
private string _url;
private int _countthreads;
private int _timeout;
private long _contentlength;
private List<Segment> _segmentList;
private List<Thread> _threadList;
public Download(string url, int timeout = 5000)
{
_url = url;
_timeout = timeout;
_segmentList = new List<Segment>();
_threadList = new List<Thread>();
}
public long GetFileSize()
{
long contentLength;
try
{
WebRequest req = HttpWebRequest.Create(_url);
req.Timeout = _timeout;
req.Method = "HEAD";
WebResponse resp = req.GetResponse();
contentLength = Convert.ToInt64(resp.Headers.Get("Content-Length"));
resp.Close();
return contentLength;
}
catch (Exception)
{
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(_url);
req.Timeout = _timeout;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
contentLength = resp.ContentLength;
resp.Close();
return contentLength;
}
catch (Exception)
{
return -1;
}
}
}
public void createDownload(FileStream file, long contentLength, int countthreads)
{
_countthreads = countthreads;
_file = file;
_contentlength = contentLength;
for (int i = 0; i < _countthreads; i++)
{
long segmentstart;
long segmentstop;
if (i != 0)
{
segmentstart = Convert.ToInt64(Math.Round(_contentlength / (double)(_countthreads) * (i), 0));
segmentstop = Convert.ToInt64(Math.Round(_contentlength / (double)(_countthreads) * (i + 1), 0));
segmentstart++;
}
else
{
segmentstart = 0;
segmentstop = Convert.ToInt64(Math.Round(_contentlength / (double)(_countthreads) * (i + 1), 0));
}
Segment segment = new Segment(file, _url, segmentstart, segmentstop);
segment.finished += new EventHandler(finishedSegment);
_threadList.Add(segment.prepare());
_segmentList.Add(segment);
}
for (int i = 0; i < _threadList.Count; i++)
{
_threadList[i].Start();
}
}
public FileStream createFile()
{
SaveFileDialog dialog = new SaveFileDialog();
dialog.ShowDialog();
if (dialog.FileName != "")
{
return (FileStream)dialog.OpenFile();
}
else
{
throw new Exception("Fail!");
}
}
public void finishedSegment(object seg, EventArgs args)
{
if (_segmentList.Count > 1)
{
_segmentList.Remove((Segment)seg);
}
else
{
_segmentList.Remove((Segment)seg);
_file.Close();
}
}
public List<long[]> getStats()
{
List<long[]> stats = new List<long[]>();
foreach (Segment seg in _segmentList)
{
long[] stat = seg.getStats();
stats.Add(stat);
}
return stats;
}
}
PHP Code:
class Segment
{
public event EventHandler finished;
private FileStream _fs;
private Stream _downstream;
private long _start;
private long _end;
private long _downloaded;
private int _bufferlength;
private string _url;
private Thread _loaderThread;
private HttpWebResponse _resp;
public Segment(FileStream fs, string url, long start, long end, int bufferlength = 256)
{
_fs = fs;
_start = start;
_end = end;
_downloaded = 0;
_bufferlength = bufferlength;
_url = url;
}
public Thread prepare()
{
try
{
HttpWebRequest part = (HttpWebRequest)WebRequest.Create(_url);
part.AddRange(_start);
_resp = (HttpWebResponse)part.GetResponse();
_downstream = _resp.GetResponseStream();
_loaderThread = new Thread(delegate() { doLoad(); });
return _loaderThread;
}
catch (Exception)
{
throw new Exception("Segmentierter Download konnte nicht erstellt werden!");
}
}
private void doLoad()
{
bool nextbytes = true;
byte[] buffer = new byte[_bufferlength];
int howmuchread = 0;
long pos = 0;
while ((howmuchread = _downstream.Read(buffer, 0, _bufferlength)) != 0 && nextbytes)
{
if (_end != -1)
{
if (_start + pos + howmuchread > _end)
{
howmuchread -= (int)((pos + (long)howmuchread) - (_end - _start));
nextbytes = false;
}
}
writeFile(_fs, buffer, (int)(_start + pos), howmuchread);
pos += howmuchread;
_downloaded += howmuchread;
}
_downstream.Close();
_resp.Close();
if (finished != null)
{
finished(this, new EventArgs());
}
}
public void writeFile(FileStream fs, byte[] buffer, int start, int size)
{
if (!Monitor.TryEnter(fs, 2000))
{
}
else
{
try
{
fs.Seek(start, SeekOrigin.Begin);
fs.Write(buffer, 0, size);
}
finally
{
Monitor.Exit(fs);
}
}
}
internal long[] getStats()
{
long[] stat = new long[3];
stat[0] = _start;
stat[1] = _downloaded;
stat[2] = _end;
return stat;
}
}






