Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SQL Server:如何将存储在varbinary(max)字段中的文件(pdf、doc、txt…)复制到CLR存储过程中的文件?_C#_Sql Server_Delphi_Sqlclr_Varbinary - Fatal编程技术网

C# SQL Server:如何将存储在varbinary(max)字段中的文件(pdf、doc、txt…)复制到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

我问这个问题是作为我的后续行动

已经发布了一个使用bcp和xp_cmdshell的解决方案,这不是我想要的解决方案

我是c#的新手(因为我是一名Delphi开发人员),无论如何,我能够按照教程创建一个简单的CLR存储过程

我的任务是将文件从客户端文件系统移动到服务器文件系统(可以使用远程IP访问服务器,因此我不能使用共享文件夹作为目标,这就是我需要CLR存储过程的原因)

因此,我计划:

  • 从Delphi将文件存储在临时表的varbinary(max)列中
  • 调用CLR存储过程,使用varbinary(max)字段中包含的数据在所需路径上创建文件
  • 假设我需要将C:\MyFile.pdf移动到Z:\MyFile.pdf,其中C:是本地系统上的硬盘驱动器,Z:是服务器上的硬盘驱动器。C在纽约,Z在伦敦,他们之间没有VPN,只有https连接

    我提供了下面的代码(不工作),有人可以修改使其工作?这里我假设有一个名为MyTable的表,它有两个字段:ID(int)和DATA(varbinary(max))。请注意,如果该表是真正的临时表,或者只是临时存储数据的表,则没有区别。如果有一些异常处理代码(以便我可以管理“无法保存文件”异常),我将不胜感激

    我想能够写一个新的文件或覆盖文件,如果已经存在

    [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中有效