FTPクライアントとして機能するセクションを備えたC#WPFアプリケーションがあり、リモートサーバー上のファイルを一覧表示し、ユーザーがそれらをダウンロードできるようにします。ユーザーがファイル リストから自分のマシン (つまり、Windows Explorer シェル) にファイルをドラッグ アンド ドロップできるようにしたいと考えています。
これを実現するために、Delay のブログ の VirtualFileDataObject コードを使用しAction<Stream>
、SetData
. これは、小さなファイルでうまく機能します。
私の問題は、私が扱っているファイルのいくつかが非常に大きい (2 GB 以上) であり、VirtualFileDataObject
クラスがストリームを処理する方法には、全体をメモリに読み込むことが含まれているため、「十分なストレージがありません」というエラーがスローされる可能性があることです。それらの非常に大きなファイルの場合。
VirtualFileDataObject
コードの関連セクションを以下に示します。ストリーム全体がメモリ内にある必要がないように、このコードを書き直すにはどうすればよいですか?
public void SetData(short dataFormat, int index, Action<Stream> streamData) {
_dataObjects.Add(
new DataObject {
FORMATETC = new FORMATETC {
cfFormat = dataFormat,
ptd = IntPtr.Zero,
dwAspect = DVASPECT.DVASPECT_CONTENT,
lindex = index,
tymed = TYMED.TYMED_ISTREAM
},
GetData = () => {
// Create IStream for data
var ptr = IntPtr.Zero;
var iStream = NativeMethods.CreateStreamOnHGlobal(IntPtr.Zero, true);
if (streamData != null) {
// Wrap in a .NET-friendly Stream and call provided code to fill it
using (var stream = new IStreamWrapper(iStream)) {
streamData(stream);
}
}
// Return an IntPtr for the IStream
ptr = Marshal.GetComInterfaceForObject(iStream, typeof(IStream));
Marshal.ReleaseComObject(iStream);
return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
},
});
}
特に、次のセクションがGetData
原因です。
// Wrap in a .NET-friendly Stream and call provided code to fill it
using (var stream = new IStreamWrapper(iStream)) {
streamData(stream);
}
streamData
はAction<stream>
、実際のファイル データをストリームに書き込む I が提供するものです。私のデリゲートは、ファイルを開いて、提供されたストリームにバイトを読み取っているだけです。
この最後のステップを回避する方法はありますか? ファイル ストリームを直接渡して Explorer シェルから読み取る方法はありますか? 私がiStream
持っている.NETファイルストリームへのポインターに置き換えるようなことを考えています...しかし、それを行うための構文を知るには、COM相互運用について十分に知りません。ヒント/方向性をいただければ幸いです。