【发布时间】:2020-04-24 19:32:02
【问题描述】:
大家好,晚上好/早上好,所以我正在尝试实现一个类来处理 http 请求的查找功能,以加载 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");
}
}
我真的不知道自己缺少什么,任何帮助都会非常非常非常感激。
【问题讨论】:
标签: c# http stream zip remote-access