Hello, it looks like AWS S3 provides TransferUtility.OpenStream
method, which returns a read-only stream that you can pass to NodeContent.CreateReadOnlyContent
(similar to how it's done in FileServerCustomFS sample's DriveFileSystemProvider class).
However, I'm afraid that the stream returned by TransferUtility.OpenStream
is not seekable, which means it doesn't actually fit SFTP protocol's requirements. But as long as SFTP clients are not actually going to use seeking when reading from the file, you might work around this by simulating a seekable stream using the PseudoSeekableStream
class below.
Sample usage - get readable stream from AWS S3, wrap it by PseudoSeekableStream
and pass it to NodeContent.CreateReadOnlyContent
:
protected override NodeContent GetContent(NodeBase node, NodeContentParameters contentParameters)
{
...
Stream awsStream = TransferUtility.OpenStream(...)
Stream stream = new PseudoSeekableStream(awsStream);
return NodeContent.CreateReadOnlyContent(stream);
}
PseudoSeekableStream source:
public class PseudoSeekableStream : Stream
{
private readonly Stream _inner;
private long _position;
private long? _length;
public PseudoSeekableStream(Stream inner)
{
_inner = inner;
}
public override bool CanRead
{
get { return _inner.CanRead; }
}
public override bool CanSeek
{
get { return _inner.CanSeek; }
}
public override bool CanWrite
{
get { return _inner.CanWrite; }
}
public override long Length
{
get { throw new NotSupportedException(); }
}
public override long Position
{
get { return _position; }
set { _position = value; }
}
public override void Flush()
{
}
public override int Read(byte[] buffer, int offset, int count)
{
if (_length.HasValue)
return 0;
int n = _inner.Read(buffer, offset, count);
if (n > 0)
{
_position += n;
}
else
{
_length = _position;
}
return n;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Begin)
throw new NotSupportedException();
if (offset != _position)
{
if (!_length.HasValue || offset < _length)
throw new NotSupportedException();
}
return _position;
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_inner.Close();
}
}
}