Сохранив какой-либо файл к в базе данных, просто преобразуйте его в массив байтов?

Действительно ли преобразование является файлом к массиву байтов лучший способ сохранить на диск КАКОЙ-ЛИБО формат файла или столбец двоичных данных var базы данных?

Таким образом, если кто-то хочет сохранить .gif или .doc/.docx или файл pdf, я могу просто преобразовать его в bytearray UFT8 и сохранить его к дб как поток байтов?

66
задан Blankman 5 April 2010 в 15:58
поделиться

5 ответов

Поскольку не указано, какую базу данных вы имеете в виду, я предполагаю SQL Server. Нижеприведенное решение работает как для 2005, так и для 2008 года.

Вы должны создать таблицу с VARBINARY (MAX) в качестве одного из столбцов. В моем примере я создал таблицу Raporty со столбцом RaportPlik , являющимся столбцом VARBINARY (MAX) .

Метод помещения файла в базу данных с диска :

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();
    }
}

Этот метод заключается в том, чтобы получить файл из базы данных и сохранить его на диске :

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);
            }
    }
}

Этот метод должен получить файл из базы данных и поместить его как 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;
}

Этот метод должен поместить MemoryStream в базу данных:

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;
    }

Удачного кодирования: -)

144
ответ дан 24 November 2019 в 14:53
поделиться

Да, как правило, лучший способ сохранить файл в базе данных - это сохранить массив байтов в столбце BLOB. Возможно, вам понадобится пара столбцов для дополнительного хранения метаданных файла, таких как имя, расширение и т. Д.

Хранить файлы в базе данных - не всегда хорошая идея - например, размер базы данных будет быстро расти, если вы храните в ней файлы. Но все зависит от вашего сценария использования.

2
ответ дан 24 November 2019 в 14:53
поделиться

Несмотря на то, что вы можете хранить файлы таким образом, это требует значительных компромиссов:

  • Большинство баз данных не оптимизированы для гигантских объемов двоичных данных, и производительность запросов часто резко снижается из-за раздувания таблиц, даже с индексами. (SQL Server 2008 с типом столбца FILESTREAM является исключением из правила.)
  • Резервное копирование / репликация БД становится чрезвычайно медленным.
  • Гораздо проще обрабатывать поврежденный диск с 2 миллионами образов - просто замените диск в RAID - чем поврежденную таблицу БД.
  • Если вы случайно удалите дюжину изображений в файловой системе, ваши операторы могут довольно легко заменить их из резервной копии, а поскольку индекс таблицы по сравнению с ним крошечный, его можно быстро восстановить. Если вы случайно удалите дюжину изображений в гигантской таблице базы данных, вам придется долго и мучительно ждать восстановления БД из резервной копии, тем самым парализуя всю вашу систему.

Это лишь некоторые из недостатков, которые я могу придумать не сразу. Для крошечных проектов, возможно, стоит хранить файлы таким образом, но если вы разрабатываете программное обеспечение корпоративного уровня, я настоятельно рекомендую этого не делать.

8
ответ дан 24 November 2019 в 14:53
поделиться

Это действительно зависит от сервера базы данных.

Например, SQL Server 2008 поддерживает тип данных FILESTREAM именно для этой ситуации.

Кроме того, если вы используете MemoryStream , у него есть метод ToArray () , который преобразуется в байт [] - это может быть используется для заполнения поля varbinary ..

7
ответ дан 24 November 2019 в 14:53
поделиться

Какую базу данных вы используете? обычно вы не сохраняете файлы в базе данных, но я думаю, что sql 2008 поддерживает это ...

Файл представляет собой двоичные данные, поэтому UTF 8 здесь не имеет значения ..

UTF 8 имеет значение, когда вы пытаетесь преобразовать строка в массив байтов ... не файл в массив байтов.

1
ответ дан 24 November 2019 в 14:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: