嗨,大家晚上好,我正在尝试实现一个类,它将处理http请求的seek函数,加载zip文件,并提取特定的文件,而不是下载所有的档案,到目前为止,它在开始时工作得很好,但随着进一步的发展,错过了一些文件,或永远得到股票,我写的类是像下面。(我从github上的某个地方取来的,并进行了真正的修改)
public class HTTPDownloadStream : Stream
{
private string _serverUri;
private MemoryStream StoringStream = null;
private HttpWebRequest _request;
private HttpWebResponse _response;
private Stream _responseStream = null;
public Exception CaughtException;
private long TotalLength = 0;
public long BytePlace = 0;
public long LoadRange = 0;
public HTTPDownloadStream(string serverUri)
{
_serverUri = serverUri;
StartHTTPDOwnload();
}
private void StartHTTPDOwnload(long from = 0)
{
// This can be replaced with the Http equivalents
_request = (HttpWebRequest)WebRequest.Create(_serverUri);
_request.AddRange(from);
LoadRange = from;
_response = (HttpWebResponse)_request.GetResponse();
_responseStream = _response.GetResponseStream();
if(TotalLength == 0)
{
TotalLength = _response.ContentLength;
}
if (StoringStream != null)
{
StoringStream.Close();
}
StoringStream = new MemoryStream();
int readbytes = 0;
while (true)
{
byte[] readdata = new byte[4096];
int len = _responseStream.Read(readdata, 0, readdata.Length);
readbytes += len;
if (len > 0 && readbytes < 102000)
{
StoringStream.Write(readdata, 0, len);
}
else
{
break;
}
}
StoringStream.Position = 0;
_responseStream.Close();
_response.Close();
_responseStream = null;
_response = null;
_request = null;
//if (_responseStream != null)
// _responseStream.ReadTimeout = 10000; // Set timeout to 10 seconds for testing.
}
public override int Read(byte[] buffer, int offset, int count)
{
int attempts = 0;
// Adjust the maximum attempts according to your needs
while (attempts++ < 5)
{
if (StoringStream == null)
{
StartHTTPDOwnload();
}
try
{
// This will throw a timeout exception if the connection is interrupted.
// Will throw null exception if failed to open (start); this will also retry.
int done = StoringStream.Read(buffer, offset, count);
BytePlace += done;
long placereached = (BytePlace - LoadRange);
if(placereached >= StoringStream.Length)
{
Seek(1, SeekOrigin.Current);
int ndone = StoringStream.Read(buffer, done, count - done);
BytePlace += ndone;
done += ndone;
}
return done;
}
catch (Exception ex)
{
CaughtException = ex;
// Close ftp resources if possible. Set instances to null to force restart.
Close();
}
}
return 0;
}
public override void Close()
{
if (_responseStream != null)
{
try
{
StoringStream.Close();
}
catch
{
// No action required
}
}
StoringStream = null;
}
// Implement the Stream methods
public override void Flush()
{
StoringStream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
if(origin == SeekOrigin.Begin)
{
BytePlace = offset;
}
else
{
BytePlace += offset;
}
long newplace = BytePlace - LoadRange;
if(newplace < 0 || newplace >= StoringStream.Length)
{
StartHTTPDOwnload((BytePlace));
}
else
{
StoringStream.Seek(newplace, SeekOrigin.Begin);
}
return BytePlace;
}
public override void SetLength(long value)
{
StoringStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
StoringStream.Write(buffer, offset, count);
}
public override bool CanRead
{
get { return StoringStream.CanRead; }
}
public override bool CanSeek
{
get { return StoringStream.CanSeek; }
}
public override bool CanWrite
{
get { return StoringStream.CanWrite; }
}
public override long Length
{
get { return TotalLength; }
}
public override long Position
{
get { return BytePlace; }
set { BytePlace = value; } // never gets called, no worries
}
}
使用它。
HTTPDownloadStream httpstream = new HTTPDownloadStream("http://update.dbankcdn.com/TDS/data/files/p3/s15/G5398/g1755/v386379/f1/full/update_full_base.zip");
ZipInputStream stream = new ZipInputStream(httpstream);
while(true)
{
ZipEntry entry = stream.GetNextEntry();
if(entry != null)
{
MessageBox.Show(entry.FileName + " | " + entry.CompressedSize);
}
else
{
MessageBox.Show("Done");
}
}
我真的不知道我缺了什么,任何帮助将是真的,真的,真的很感激。
一直在玩,现在只是莫名其妙的工作。
class HTTPStream : Stream
{
private string _serverUri;
private MemoryStream StoringStream = null;
private HttpWebRequest _request;
private HttpWebResponse _response;
private Stream _responseStream = null;
public Exception CaughtException;
private long TotalLength = 0;
public long BytePlace = 0;
public long LoadRange = 0;
public HTTPStream(string serverUri)
{
_serverUri = serverUri;
StartHTTPDOwnload();
}
private void StartHTTPDOwnload(long from = 0)
{
_request = (HttpWebRequest)WebRequest.Create(_serverUri);
_request.AddRange(from, from + 300000);
LoadRange = from;
_response = (HttpWebResponse)_request.GetResponse();
_responseStream = _response.GetResponseStream();
if (TotalLength == 0)
{
TotalLength = _response.ContentLength;
}
if (StoringStream != null)
{
StoringStream.Close();
}
StoringStream = new MemoryStream();
int readbytes = 0;
while (true)
{
byte[] readdata = new byte[4096];
int len = _responseStream.Read(readdata, 0, readdata.Length);
readbytes += len;
if (len > 0 && readbytes < 250000)
{
StoringStream.Write(readdata, 0, len);
}
else
{
break;
}
}
StoringStream.Position = 0;
_responseStream.Close();
_response.Close();
_responseStream = null;
_response = null;
_request = null;
}
public override int Read(byte[] buffer, int offset, int count)
{
int attempts = 0;
while (attempts++ < 5)
{
if (StoringStream == null)
{
StartHTTPDOwnload();
}
try
{
int done = StoringStream.Read(buffer, offset, count);
BytePlace += done;
long placereached = (BytePlace - LoadRange);
if (placereached >= StoringStream.Length)
{
Seek(0, SeekOrigin.Current);
int ndone = StoringStream.Read(buffer, done, count - done);
BytePlace += ndone;
done += ndone;
}
return done;
}
catch (Exception ex)
{
CaughtException = ex;
Close();
}
}
return 0;
}
public override void Close()
{
if (StoringStream != null)
{
try
{
StoringStream.Close();
}
catch
{
}
}
StoringStream = null;
}
public override void Flush()
{
StoringStream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin == SeekOrigin.Begin)
{
BytePlace = offset;
}
else
{
BytePlace += offset;
}
long newplace = BytePlace - LoadRange;
if (newplace < 0 || newplace >= StoringStream.Length)
{
StartHTTPDOwnload((BytePlace));
}
else
{
StoringStream.Seek(newplace, SeekOrigin.Begin);
}
return BytePlace;
}
public override void SetLength(long value)
{
StoringStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
StoringStream.Write(buffer, offset, count);
}
public override bool CanRead
{
get { return StoringStream.CanRead; }
}
public override bool CanSeek
{
get { return StoringStream.CanSeek; }
}
public override bool CanWrite
{
get { return StoringStream.CanWrite; }
}
public override long Length
{
get { return TotalLength; }
}
public override long Position
{
get { return BytePlace; }
set { BytePlace = value; } // never gets called, no worries
}
}
HTTPStream httpstream = new HTTPStream(GetPackageURL(url));
ZipInputStream stream = new ZipInputStream(httpstream);
while (true)
{
ZipEntry entry = stream.GetNextEntry();
if (entry != null)
{
if (entry.Name.Contains("SOFTWARE_VER_LIST.mbn"))
{
int read = 4096;
byte[] buffer = new byte[read];
string content = "";
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
content += Encoding.UTF8.GetString(buffer, 0, read);
}
romDetails.SupportedVersions = content.Split('\n');
break;
}
}
else
{
MessageBox.Show("Seems like I couldn't load some data :(", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
}