2010-04-05 23 views
44

Chuyển đổi tệp thành mảng byte cách tốt nhất để lưu bất kỳ định dạng tệp nào vào đĩa hoặc cột nhị phân var cơ sở dữ liệu?Lưu bất kỳ tệp nào vào cơ sở dữ liệu, chỉ cần chuyển đổi nó thành một mảng byte?

Vì vậy, nếu ai đó muốn lưu tệp .gif hoặc .doc/.docx hoặc .pdf, tôi có thể chỉ chuyển đổi nó thành một bytearray UFT8 và lưu nó vào db dưới dạng luồng byte không?

Trả lời

102

Vì nó không được đề cập đến cơ sở dữ liệu bạn có nghĩa là tôi giả sử SQL Server. Giải pháp bên dưới hoạt động cho cả năm 2005 và 2008.

Bạn phải tạo bảng có VARBINARY(MAX) làm một trong các cột. Trong ví dụ của tôi, tôi đã tạo Bảng Raporty với cột RaportPlik là cột VARBINARY(MAX).

Phương pháp đặt file vào cơ sở dữ liệu từ drive:

public static void databaseFilePut(string varFilePath) { 
    byte[] file; 
    using (var stream = new FileStream(varFilePath, FileMode.Open, FileAccess.Read)) { 
     using (var reader = new BinaryReader(stream)) { 
      file = reader.ReadBytes((int) stream.Length);  
     }   
    } 
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
    using (var sqlWrite = new SqlCommand("INSERT INTO Raporty (RaportPlik) Values(@File)", varConnection)) { 
     sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file; 
     sqlWrite.ExecuteNonQuery(); 
    } 
} 

Phương pháp này là để có được file từ cơ sở dữ liệu và lưu nó vào drive:

public static void databaseFileRead(string varID, string varPathToNewLocation) { 
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
    using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) { 
     sqlQuery.Parameters.AddWithValue("@varID", varID); 
     using (var sqlQueryResult = sqlQuery.ExecuteReader()) 
      if (sqlQueryResult != null) { 
       sqlQueryResult.Read(); 
       var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))]; 
       sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length); 
       using (var fs = new FileStream(varPathToNewLocation, FileMode.Create, FileAccess.Write)) 
        fs.Write(blob, 0, blob.Length); 
      } 
    } 
} 

Phương pháp này là để lấy file từ cơ sở dữ liệu và đặt nó là MemoryStream:

public static MemoryStream databaseFileRead(string varID) { 
    MemoryStream memoryStream = new MemoryStream(); 
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
    using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) { 
     sqlQuery.Parameters.AddWithValue("@varID", varID); 
     using (var sqlQueryResult = sqlQuery.ExecuteReader()) 
      if (sqlQueryResult != null) { 
       sqlQueryResult.Read(); 
       var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))]; 
       sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length); 
       //using (var fs = new MemoryStream(memoryStream, FileMode.Create, FileAccess.Write)) { 
       memoryStream.Write(blob, 0, blob.Length); 
       //} 
      } 
    } 
    return memoryStream; 
} 

Phương pháp này là đưa MemoryStream vào cơ sở dữ liệu:

public static int databaseFilePut(MemoryStream fileToPut) { 
     int varID = 0; 
     byte[] file = fileToPut.ToArray(); 
     const string preparedCommand = @" 
        INSERT INTO [dbo].[Raporty] 
           ([RaportPlik]) 
         VALUES 
           (@File) 
         SELECT [RaportID] FROM [dbo].[Raporty] 
      WHERE [RaportID] = SCOPE_IDENTITY() 
        "; 
     using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
     using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) { 
      sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file; 

      using (var sqlWriteQuery = sqlWrite.ExecuteReader()) 
       while (sqlWriteQuery != null && sqlWriteQuery.Read()) { 
        varID = sqlWriteQuery["RaportID"] is int ? (int) sqlWriteQuery["RaportID"] : 0; 
       } 
     } 
     return varID; 
    } 

Chúc mừng mã hóa :-)

1

Bạn đang sử dụng cơ sở dữ liệu nào? bình thường bạn không lưu tập tin vào một cơ sở dữ liệu nhưng tôi nghĩ rằng sql 2008 có hỗ trợ cho nó ...

Một tập tin là dữ liệu nhị phân do đó UTF 8 không quan trọng ở đây ..

UTF 8 vấn đề khi bạn cố gắng để chuyển đổi một chuỗi thành một mảng byte ... không phải là một tệp thành mảng byte.

0

Có, cách tốt nhất để lưu trữ tệp trong cơ sở dữ liệu là lưu mảng byte vào cột BLOB. Có thể bạn sẽ muốn có một vài cột để lưu trữ thêm siêu dữ liệu của tệp như tên, tiện ích mở rộng, v.v.

Không phải lúc nào cũng lưu ý các tệp trong cơ sở dữ liệu - ví dụ: kích thước cơ sở dữ liệu sẽ tăng nhanh nếu bạn lưu trữ tệp trong đó. Nhưng tất cả phụ thuộc vào kịch bản sử dụng của bạn.

7

Nó thực sự phụ thuộc vào máy chủ cơ sở dữ liệu.

Ví dụ: SQL Server 2008 hỗ trợ một kiểu dữ liệu FILESTREAM cho chính xác trường hợp này.

Ngoài ra, nếu bạn sử dụng một MemoryStream, nó có một phương pháp ToArray() mà sẽ chuyển đổi sang một byte[] - điều này có thể được sử dụng cho một lĩnh vực Populating varbinary ..

9

Trong khi bạn có thể lưu trữ các file theo cách này, nó có sự cân bằng đáng kể:

  • Hầu hết các DB không được tối ưu hóa cho số lượng khổng lồ dữ liệu nhị phân và hiệu suất truy vấn thường giảm đáng kể khi bảng bloats, ngay cả với chỉ mục. (SQL Server 2008, với kiểu cột FILESTREAM, là ngoại lệ cho quy tắc.)
  • Sao lưu/sao chép DB trở nên cực kỳ chậm.
  • Việc xử lý ổ đĩa bị hỏng với 2 triệu hình ảnh dễ dàng hơn rất nhiều - chỉ cần thay thế đĩa trên RAID - so với bảng DB bị hỏng.
  • Nếu bạn vô tình xóa hàng tá ảnh trên hệ thống tệp, các nhân viên của bạn có thể thay thế chúng dễ dàng từ bản sao lưu và vì chỉ mục bảng nhỏ khi so sánh, nó có thể được khôi phục nhanh chóng. Nếu bạn vô tình xóa một tá hình ảnh trong một bảng cơ sở dữ liệu khổng lồ, bạn có một sự chờ đợi lâu dài và đau đớn để khôi phục DB từ bản sao lưu, làm tê liệt toàn bộ hệ thống của bạn trong thời gian chờ đợi.

Đây chỉ là một trong những hạn chế mà tôi có thể thoát ra khỏi đỉnh đầu. Đối với các dự án nhỏ, nó có thể đáng lưu trữ các tệp theo cách này, nhưng nếu bạn đang thiết kế phần mềm cấp doanh nghiệp, tôi sẽ khuyên bạn nên chống lại nó.

2

Xác nhận tôi đã có thể sử dụng câu trả lời đăng bởi MadBoy và chỉnh sửa bởi Otiel trên cả MS SQL Server 2012 và 2014 ngoài các phiên bản được liệt kê trước đây bằng cách sử dụng các cột varbinary (MAX).

Nếu bạn tự hỏi tại sao bạn không thể "Filestream" (ghi chú trong câu trả lời riêng) làm kiểu dữ liệu trong trình thiết kế bảng SQL Server hoặc tại sao bạn không thể đặt kiểu dữ liệu của cột thành "Filestream" bằng T-SQL, FILESTREAM là một thuộc tính lưu trữ của kiểu dữ liệu varbinary (MAX). Nó không phải là một kiểu dữ liệu riêng của nó.

Xem những bài viết về việc thành lập và cho phép FileStream trên một cơ sở dữ liệu: https://msdn.microsoft.com/en-us/library/cc645923(v=sql.120).aspx

http://www.kodyaz.com/t-sql/default-filestream-filegroup-is-not-available-in-database.aspx

khi cấu hình, một FileStream kích hoạt varbinary (max) cột có thể được thêm vào như vậy:

ALTER TABLE Tên bảng

ADD ColumnName varbinary (tối đa) FILESTREAM NULL

GO

Các vấn đề liên quan