gpt4 book ai didi

c# - 将大型虚拟文件从 C# 拖放到 Windows 资源管理器

转载 作者:太空狗 更新时间:2023-10-29 23:24:50 25 4
gpt4 key购买 nike

我有一个 C# WPF 应用程序,其中有一个部分用作 FTP 客户端,列出远程服务器上的文件并允许用户下载它们。我希望用户能够将文件列表中的文件拖放到他们自己的计算机上(即拖放到 Windows 资源管理器外壳中)。

为此,我使用了 VirtualFileDataObject code from Delay's blog , 使用 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);
}

streamDataAction<stream>我提供将实际文件数据写入流的方法。我的委托(delegate)只是打开一个文件并将字节读入提供的流中。

有没有办法避免这最后一步,也许以某种方式直接传递文件流以供 Explorer shell 从中读取?我在想类似替换 iStream 的东西带有指向 .NET 文件流的指针我已经...但是我对 COM 互操作的了解还不够,甚至不知道这样做的语法。任何提示/方向将不胜感激!

最佳答案

经过更多的谷歌搜索和跌跌撞撞,不断尝试,我找到了一些可行的方法,但我仍然愿意接受更好的解决方案。现在,当删除操作发生时,我将文件检索到一个临时位置,然后使用 SHCreateStreamOnFileEx打开指向该位置的 IStream。修改后的部分 GetData lambda 如下:

GetData = () => {
var filename = getFilename();

IStream stream = null;
NativeMethods.SHCreateStreamOnFileEx(filename, NativeMethods.STGM_FAILIFTHERE, NativeMethods.FILE_ATTRIBUTE_NORMAL, false, null, ref stream);
var ptr = Marshal.GetComInterfaceForObject(stream, typeof(IStream));
Marshal.ReleaseComObject(stream);
return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
}

正如我所说,我不知道这是否是最好的方法,或者我是否可以更干净地管理它,但这似乎有效。

关于c# - 将大型虚拟文件从 C# 拖放到 Windows 资源管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12410114/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com