C# SQL Server:如何将存储在varbinary(max)字段中的文件(pdf、doc、txt…)复制到CLR存储过程中的文件?
我问这个问题是作为我的后续行动 已经发布了一个使用bcp和xp_cmdshell的解决方案,这不是我想要的解决方案 我是c#的新手(因为我是一名Delphi开发人员),无论如何,我能够按照教程创建一个简单的CLR存储过程 我的任务是将文件从客户端文件系统移动到服务器文件系统(可以使用远程IP访问服务器,因此我不能使用共享文件夹作为目标,这就是我需要CLR存储过程的原因) 因此,我计划:C# SQL Server:如何将存储在varbinary(max)字段中的文件(pdf、doc、txt…)复制到CLR存储过程中的文件?,c#,sql-server,delphi,sqlclr,varbinary,C#,Sql Server,Delphi,Sqlclr,Varbinary,我问这个问题是作为我的后续行动 已经发布了一个使用bcp和xp_cmdshell的解决方案,这不是我想要的解决方案 我是c#的新手(因为我是一名Delphi开发人员),无论如何,我能够按照教程创建一个简单的CLR存储过程 我的任务是将文件从客户端文件系统移动到服务器文件系统(可以使用远程IP访问服务器,因此我不能使用共享文件夹作为目标,这就是我需要CLR存储过程的原因) 因此,我计划: 从Delphi将文件存储在临时表的varbinary(max)列中 调用CLR存储过程,使用varbinary
[Microsoft.SqlServer.Server.SqlProcedure]
public static void VarbinaryToFile(int TableId)
{
using (SqlConnection connection = new SqlConnection("context connection=true"))
{
connection.Open();
SqlCommand command = new SqlCommand("select data from mytable where ID = @TableId", connection);
command.Parameters.AddWithValue("@TableId", TableId);
// This was the sample code I found to run a query
//SqlContext.Pipe.ExecuteAndSend(command);
// instead I need something like this (THIS IS META_SYNTAX!!!):
SqlContext.Pipe.ResultAsStream.SaveToFile('z:\MyFile.pdf');
}
}
(一个子问题是:这种方法是否正确,或者是否有一种方法可以直接将数据传递到CLR存储过程,这样我就不需要使用临时表?
如果子问题的答案是否定的,您能描述一下避免临时表的方法吗?那么有没有比我上面描述的更好的方法(=临时表+存储过程)?直接将dataastream从客户端应用程序传递到CLR存储过程的方法?(我的文件可以是任意大小,但也可以非常大)请参见为什么要将这些文件放入数据库?如果您有http/https连接,您可以将文件上载到服务器,写入受保护的数据库,并创建一个页面列出这些文件,并提供下载链接。若您想存储一些额外的信息,可以将其写入数据库。您只需要在服务器端更改文件名(使用唯一的名称)。经过一些研究,我得出结论认为这没有意义,最好放弃对2005的支持,使用2008 fielstream功能。我可以在2005年和2008年之间选择条件逻辑,并且只在2005年使用filestream 有没有一种方法可以直接将数据传递给CLR存储过程,这样我就不需要使用临时表了 是的,将二进制文件传递给SQLCLR存储过程并让它将内容写入磁盘,而不需要先将这些内容放入表中(临时或实际),这是可能的,而且相当简单
[Microsoft.SqlServer.Server.SqlProcedure]
公共静态void SaveFileToLocalDisk([SqlFacet(MaxSize=-1)]SqlBytes FileContents,
SqlString目标路径)
{
if(FileContents.IsNull | | DestinationPath.IsNull)
{
抛出新的ArgumentException(“严重?”);
}
File.writealBytes(DestinationPath.Value,FileContents.Buffer);
返回;
}
或者,因为您说过文件有时很大,所以以下内容在内存使用方面应该更容易,因为它使用了流功能:
[Microsoft.SqlServer.Server.SqlProcedure]
公共静态无效保存文件ToLocalDiskStreamed(
[SqlFacet(MaxSize=-1)]SqlBytes文件内容,SqlString DestinationPath)
{
if(FileContents.IsNull | | DestinationPath.IsNull)
{
抛出新的ArgumentException(“严重?”);
}
int _ChunkSize=1024;
字节[]_缓冲区=新字节[_ChunkSize];
使用(FileStream _File=newfilestream(DestinationPath.Value,FileMode.Create))
{
长_位置=0;
长字节读取=0;
while(true)
{
_BytesRead=FileContents.Read(_位置,_缓冲区,0,_块大小);
_Write(_Buffer,0,(int)_BytesRead);
_位置+=\u块大小;
if(_BytesRead<_ChunkSize | |(_Position>=FileContents.Length))
{
打破
}
}
_File.Close();
}
返回;
}
当然,包含此代码的程序集需要具有外部访问权限的权限集
在这两种情况下,您将以以下方式执行它们:
EXEC dbo.SaveFileToLocalDiskStreamed 0x2A20202A,N'C:\TEMP\SaveToDiskTest.txt';
“0x2A20202A”应提供包含以下4个字符(星号、空格、空格、星号)的文件:
**
一夜之间,我想到一件事:是否可以将本文中描述的方法也用于非常大的文件?我的意思是,通过使用链接中的示例,可以执行以下操作:exec ns_lib.dbo.ns_txt_file_write@file_name='c:\temp\test_file.txt',@file_contents=0x4D5A9000300000004000。。。。(此长列表是文件内容)?当然,将第二个参数更改为varbinary(max)。以这种方式传递的数据量是否有限制?如果这是真的,那就意味着我的子问题的答案是肯定的。没有人能比这更有用了?嘿。我知道已经5年多了,但我发布了一个答案,这个答案应该是有效的;-)。您好,我从来没有提到过2005年、2008年,而filestream对我来说是一个限制,所以我认为您的答案不清楚。现在我感到困惑。您询问了如何直接将数据传递给CLR存储过程,这样就不需要使用表。我展示了一种方法来做到这一点。我提出的方法在SQLSER中有效