2016-09-29 25 views
0

有什麼辦法,打開任何文件(.doc,.xls,.pdf等)與相關的程序保存在SQL Server作爲varbinary?打開任何文件(.doc,.xls,.pdf等)與相關的程序保存在sql server中作爲varbinary?

在服務器中創建數據庫;

create database DEV 
GO 
USE DEV 
GO 
create Table FileWarehouse 
(
Id int identity (1,1), 
FileType Nvarchar (50), 
StoredFile Varbinary (MAX) 
) 

我正在將文件存儲在數據庫中,如圖所示;

insert into FileWarehouse 
select 'docx' as FileType,* 
from OPENROWSET (BULK 'C:\SQLDOC\WILLBESAVEDINSERVER.docx', SINGLE_BLOB) 
AS X 

我可以從服務器獲取文件並保存到文件夾,如圖所示;

DECLARE 
@SQLIMG VARCHAR (MAX), 
@File VARBINARY (MAX), 
@OutputPath VARCHAR (MAX), 
@ObjectToken INT 

Select @File = StoredFile FROM FileWarehouse where FileType ='docx' -- or use id 
SET @OutputPath = 'C:\SQLDOC\OUTPUT\output_word_fromServer.docx' 
EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT 
EXEC sp_OASetProperty @ObjectToken, 'Type',1 
EXEC sp_OAMethod @ObjectToken, 'Open' 
EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @File 
EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, @OutputPath,2 
EXEC sp_OAMethod @ObjectToken, 'Close' 
EXEC sp_OADestroy @ObjectToken 
GO 

但我無法直接從數據庫打開文件;使用如下代碼;

private void btnOpenDocument_Click(object sender, EventArgs e) 
    { 
     int id = (int)dataGridView1.CurrentRow.Cells["ID"].Value; 


     SqlDataAdapter adp = new SqlDataAdapter(); 
     adp.SelectCommand = new SqlCommand("GetDocument"); 
     adp.SelectCommand.CommandType = CommandType.StoredProcedure; 
     adp.SelectCommand.Connection = ResimGaleri.ORM.Tools.Baglanti; 
     adp.SelectCommand.Parameters.Add("@ID", SqlDbType.Int).Value = sd.ID; 

     // add here extension that depends on your file type 
     string fileName = Path.GetRandomFileName() + ".txt"; 

     using (SqlConnection conn = ResimGaleri.ORM.Tools.Baglanti) 
     { 
      ResimGaleri.ORM.Tools.Baglanti.Open(); 
      using (SqlCommand cmd = adp.SelectCommand) 
      { 
       // you have to distinguish here which document, I assume that there is an `id` column 


       using (SqlDataReader dr = cmd.ExecuteReader()) 
       { 
        while (dr.Read()) 
        { 
         int size = 1024 * 1024; 
         byte[] buffer = new byte[size]; 
         int readBytes = 0; 
         int index = 0; 

         using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) 
         { 
          while ((readBytes = (int)dr.GetBytes(0, index, buffer, 0, size)) > 0) 
          { 

           fs.Write(buffer, 0, readBytes); 
           index += readBytes; 

          } 


         } 

        } 



       } 

      } 
     } 

     // open your file, the proper application will be executed because of proper file extension 
     ResimGaleri.ORM.Tools.Baglanti.Close(); 
     Process prc = new Process(); 
     prc.StartInfo.FileName = fileName; 
     prc.Start(); 

    } 
} 
+3

這樣我就可以把病毒程序插入數據庫中的此列,比使用SQL Server執行它在數據庫服務器上。我不知道是否sql服務器甚至允許這個,但我希望不是 – GuidoG

+0

如何插入病毒到哪個列?有趣。 –

+0

我想會有一些客戶端,允許這個表被填充? – GuidoG

回答

0

我在代碼中看到的問題是您保存文件「someRandomName」.txt。

因此,當您調用Process.Start時,將啓動記事本(或其他任何其他txt文件的默認程序)。

您需要在數據庫中還原文件名保存(或至少是原來的擴展,你已經做的,如果我沒有錯),所以你可以創建一個(暫時的?)文件「someRandomName」 .OriginalExtension

string fileName = Path.Combine(Path.GetRandomFileName(), dr.GetString("FileType"); 

正如@GuidoG所說的,確保所有保存在db上的文件都是安全的!

+0

我還在另一個表中添加了擴展名和文件名。 –

+0

所以用它來保存你的(臨時?)文件! –

+0

臨時文件已創建但不會以某種方式打開。 –

0

當然,我會先將文件保存在臨時位置。 然後使用我們在System.Diagnostics中的選項打開文件。這樣的:

Process.Start(fileName); 

或者,你可以使用ProcessStartInfo更多的選擇:

ProcessStartInfo processInfo = new ProcessStartInfo(fileName); 
processInfo.WindowStyle = ProcessWindowStyle.Maximized; 
Process.Start(processInfo); 
+0

臨時文件已創建,但不會以某種方式打開。 –

+0

你有什麼信息嗎?例外?你可以手動打開它嗎? – Jacob

+0

不幸,我無法打開它manualy。 –

相關問題