Hello Skay,
Welcome to the Rebex forum and thanks for your question.
LocalFileSystemProvider uses internally .NET FileStream.
In our VFS lingo FileStream is ImmediateWriteStream https://www.rebex.net/doc/api/Rebex.IO.FileSystem.NodeContent.CreateImmediateWriteContent.html
As documented.
"SaveContent method in ReadWriteFileSystemProvider is NEVER called. All data are written immediately using the suitable stream write methods."
Associated SaveContent events are not called as well. We are considering a small change - SaveContentCompleted (or similar event) would be called both for immediate and delayed streams.
You may use the following workaround for now.
1) Handle GetContentCompletedEvent.
localFileSystemProvider.GetFileSystemNotifier().GetContentCompleted += localFileSystemProvider_GetContentCompleted;
2) In GetContentCompleted event wrap returned stream to the special EventStream (see below) and handle EventStream Closed event.
private static void localFileSystemProvider_GetContentCompleted(object sender, GetContentEventArgs e)
{
if (e.ContentParameters != NodeContentParameters.WriteAccess)
{
return;
}
var eventStream = new EventStream(e.ResultContent.GetStream(), e.Node);
eventStream.Closed += EventStreamClosed;
e.ResultContent = NodeContent.CreateImmediateWriteContent(eventStream);
}
private static void EventStreamClosed(object o, EventArgs args)
{
var stream = (EventStream)o;
stream.Closed -= EventStreamClosed;
Console.WriteLine($"File { stream.Node.Path} has length {stream.Length}.");
}
3) EventStream is a special stream decorator that publishes Closed event and (re)reads current file node length.
using System;
using System.IO;
using Rebex.IO.FileSystem;
namespace SpecialEventStream
{
public class EventStream : Stream
{
private readonly Stream _stream;
public event EventHandler<EventArgs> Closed;
public EventStream(Stream stream, NodeBase node)
{
Node = node ?? throw new ArgumentNullException(nameof(node));
_stream = stream ?? throw new ArgumentNullException(nameof(stream));
}
public NodeBase Node
{
get;
}
public override void Flush()
{
_stream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
_stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
_stream.Write(buffer, offset, count);
}
public override bool CanRead => _stream.CanRead;
public override bool CanSeek => _stream.CanSeek;
public override bool CanWrite => _stream.CanWrite;
public override long Length => Node.Length;
public override long Position
{
get => _stream.Position;
set => _stream.Position = value;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_stream.Dispose();
OnClosed();
}
}
protected virtual void OnClosed()
{
Closed?.Invoke(this, EventArgs.Empty);
}
}
}
See also FileServer.FileUploaded event that may be better for your scenario.
https://www.rebex.net/doc/api/Rebex.Net.Servers.FileServer.FileUploaded.html
Hope this helps.
Rene