问题
I need to process folders inside a ZIP file from SFTP server (WinSCP) programmatically through ASP.NET Core.
Is there any way where I can get list of files inside ZIP file without downloading to local computer? As the file size would be high and won't be in a consistent manner. Any help would be appreciated.
回答1:
With SSH.NET library, it could be as easy as:
using (var client = new SftpClient(host, username, password)
{
client.Connect();
using (Stream stream = client.OpenRead("/remote/path/archive.zip"))
using (var archive = new ZipArchive(stream, ZipArchiveMode.Read))
{
foreach (var entry in archive.Entries)
{
Console.WriteLine(entry);
}
}
}
You need to reference System.IO.Compression
assembly to get the ZipArchive.
The code will only read (download) the ZIP central directory record, not whole ZIP archive.
Unfortunately, there's a bug in the library. To workaround it, you have to implement a wrapper Stream
implementation like this:
class FixStream : Stream
{
public override long Seek(long offset, SeekOrigin origin)
{
long result;
// workaround for SSH.NET bug in implementation of SeekOrigin.End
if (origin == SeekOrigin.End)
{
result = _stream.Seek(Length + offset, SeekOrigin.Begin);
}
else
{
result = _stream.Seek(offset, origin);
}
return result;
}
// passthrough implementation of the rest of Stream interface
public override bool CanRead => _stream.CanRead;
public override bool CanSeek => _stream.CanSeek;
public override bool CanWrite => _stream.CanWrite;
public override long Length => _stream.Length;
public override long Position {
get => _stream.Position; set => _stream.Position = value; }
public FixStream(Stream stream)
{
_stream = stream;
}
public override void Flush()
{
_stream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _stream.Read(buffer, offset, count);
}
public override void SetLength(long value)
{
_stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
_stream.Write(buffer, offset, count);
}
private Stream _stream;
}
And wrap the SftpFileStream
to it:
using (Stream stream = client.OpenRead("/remote/path/archive.zip"))
using (var stream2 = new FixStream(stream))
using (var archive = new ZipArchive(stream2, ZipArchiveMode.Read))
{
...
}
来源:https://stackoverflow.com/questions/63991495/list-files-inside-zip-file-located-on-sftp-server-in-c-sharp