Как сохранить формат изображения WEBP Google в базу данных с помощью C #? [Дубликат]

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

7 ответов

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

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

Метод поместить file в базу данных из 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();
    }
}

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

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

Счастливое кодирование: -)

118
ответ дан MadBoy 28 August 2018 в 10:57
поделиться

Подтверждение того, что я смог использовать ответ, отправленный MadBoy, и отредактировал Otiel как на MS SQL Server 2012, так и на 2014 в дополнение к версиям, ранее перечисленным с использованием столбцов varbinary (MAX).

Если вы интересно, почему вы не можете «Filestream» (отмеченный в отдельном ответе) как тип данных в дизайне таблицы SQL Server или почему вы не можете установить тип данных столбца на «Filestream» с помощью T-SQL, это связано с тем, что FILESTREAM является атрибутом хранения varbinary (MAX). Это не тип данных.

См. Эти статьи о настройке и включении FILESTREAM в базе данных: 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

После настройки можно включить добавочный столбец varbinary (max) с фильтром:

ALTER TABLE TableName

ADD ColumnName varbinary (max) FILESTREAM NULL

GO

2
ответ дан Brian C 28 August 2018 в 10:57
поделиться

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

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

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

8
ответ дан Dan Story 28 August 2018 в 10:57
поделиться
  • 1
    Таким образом, ваш ответ «не нужно». Извините, но это не ответ - особенно если это может быть их требование сделать это. ОП задает вопрос «как лучше всего». чтобы сделать это, а не "должен" Oни. – vapcguy 12 April 2018 в 19:42

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

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

0
ответ дан driis 28 August 2018 в 10:57
поделиться

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

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

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

7
ответ дан Oded 28 August 2018 в 10:57
поделиться

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

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

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

1
ответ дан Peter 28 August 2018 в 10:57
поделиться

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

SQL Server

Короткий ответ: Я использовал строку байта base64, которую я преобразовал в byte[], и сохранил в поле varbinary(max).

Длинный ответ :

Предположим, что вы загружаете веб-сайт, поэтому вы используете элемент управления <input id="myFileControl" type="file" /> или React DropZone. Чтобы получить файл, вы делаете что-то вроде var myFile = document.getElementById("myFileControl")[0]; или myFile = this.state.files[0];.

Оттуда я бы получил строку base64, используя здесь код: Преобразование input = file в массив байтов (используйте функцию UploadFile2).

Тогда я бы получил эту строку, имя файла (myFile.name) и тип (myFile.type) в объект JSON:

var myJSONObj = {
    file: base64string,
    name: myFile.name,
    type: myFile.type,
}

и опубликовать файл на сервере сервера MVC с использованием XMLHttpRequest, указав Content-Type application/json: xhr.send(JSON.stringify(myJSONObj);. Вы должны создать ViewModel, чтобы связать его с:

public class MyModel
{
    public string file { get; set; }
    public string title { get; set; }
    public string type { get; set; }
}

и указать [FromBody]MyModel myModelObj в качестве переданного параметра:

[System.Web.Http.HttpPost]  // required to spell it out like this if using ApiController, or it will default to System.Mvc.Http.HttpPost
public virtual ActionResult Post([FromBody]MyModel myModelObj)

Затем вы можете добавить это в эту функцию и сохранить его с помощью Entity Framework:

MY_ATTACHMENT_TABLE_MODEL tblAtchm = new MY_ATTACHMENT_TABLE_MODEL();
tblAtchm.Name = myModelObj.name;
tblAtchm.Type = myModelObj.type;
tblAtchm.File = System.Convert.FromBase64String(myModelObj.file);
EntityFrameworkContextName ef = new EntityFrameworkContextName();
ef.MY_ATTACHMENT_TABLE_MODEL.Add(tblAtchm);
ef.SaveChanges();

tblAtchm.File = System.Convert.FromBase64String(myModelObj.file); является оперативной линией.

Вам понадобится модель для представления таблицы базы данных:

public class MY_ATTACHMENT_TABLE_MODEL 
{
    [Key]
    public byte[] File { get; set; }  // notice this change
    public string Name { get; set; }
    public string Type { get; set; }
}

Это сохранит данные в поле varbinary(max) в качестве byte[]. Name и Type были соответственно nvarchar(250) и nvarchar(10). Вы можете включить размер, добавив его в таблицу в качестве столбца int & amp; MY_ATTACHMENT_TABLE_MODEL в качестве public int Size { get; set;} и добавьте в строку tblAtchm.Size = System.Convert.FromBase64String(myModelObj.file).Length; выше.

Oracle

Краткий ответ: преобразуйте его в byte[], назначьте его OracleParameter ], добавьте его в свой OracleCommand и обновите поле вашей таблицы BLOB, используя ссылку на значение параметра ParameterName: :BlobParameter

Длинный ответ: когда я сделал это для Oracle, я использовал OpenFileDialog, и я получил и отправил информацию о байтах / файле следующим образом:

byte[] array;
OracleParameter param = new OracleParameter();
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "Image Files (*.jpg, *.jpeg, *.jpe)|*.jpg;*.jpeg;*.jpe|Document Files (*.doc, *.docx, *.pdf)|*.doc;*.docx;*.pdf"
if (dlg.ShowDialog().Value == true)
{
    string fileName = dlg.FileName;
    using (FileStream fs = File.OpenRead(fileName)
    {
        array = new byte[fs.Length];
        using (BinaryReader binReader = new BinaryReader(fs))
        {
            array = binReader.ReadBytes((int)fs.Length);
        }

        // Create an OracleParameter to transmit the Blob
        param.OracleDbType = OracleDbType.Blob;
        param.ParameterName = "BlobParameter";
        param.Value = array;  // <-- file bytes are here
    }
    fileName = fileName.Split('\\')[fileName.Split('\\').Length-1]; // gets last segment of the whole path to just get the name

    string fileType = fileName.Split('.')[1];
    if (fileType == "doc" || fileType == "docx" || fileType == "pdf")
        fileType = "application\\" + fileType;
    else
        fileType = "image\\" + fileType;

    // SQL string containing reference to BlobParameter named above
    string sql = String.Format("INSERT INTO YOUR_TABLE (FILE_NAME, FILE_TYPE, FILE_SIZE, FILE_CONTENTS, LAST_MODIFIED) VALUES ('{0}','{1}',{2},:BlobParamerter, SYSDATE)", fileName, fileType, array.Length);

    // Do Oracle Update
    RunCommand(sql, param);
}

И внутри обновления Oracle, выполненного с помощью ADO:

public void RunCommand(string sql, OracleParameter param)
{
    OracleConnection oraConn = null;
    OracleCommand oraCmd = null;
    try
    {
        string connString = GetConnString();
        oraConn = OracleConnection(connString);
        using (oraConn)
        {
            if (OraConnection.State == ConnectionState.Open)
                OraConnection.Close();

            OraConnection.Open();

            oraCmd = new OracleCommand(strSQL, oraConnection);

            // Add your OracleParameter
            if (param != null)
                OraCommand.Parameters.Add(param);

            // Execute the command
            OraCommand.ExecuteNonQuery();
        }
    }
    catch (OracleException err)
    {
       // handle exception 
    }
    finally
    {
       OraConnction.Close();
    }
}

private string GetConnString()
{
    string host = System.Configuration.ConfigurationManager.AppSettings["host"].ToString();
    string port = System.Configuration.ConfigurationManager.AppSettings["port"].ToString();
    string serviceName = System.Configuration.ConfigurationManager.AppSettings["svcName"].ToString();
    string schemaName = System.Configuration.ConfigurationManager.AppSettings["schemaName"].ToString();
    string pword = System.Configuration.ConfigurationManager.AppSettings["pword"].ToString(); // hopefully encrypted

    if (String.IsNullOrEmpty(host) || String.IsNullOrEmpty(port) || String.IsNullOrEmpty(serviceName) || String.IsNullOrEmpty(schemaName) || String.IsNullOrEmpty(pword))
    {
        return "Missing Param";
    }
    else
    {
        pword = decodePassword(pword);  // decrypt here
        return String.Format(
           "Data Source=(DESCRIPTION =(ADDRESS = ( PROTOCOL = TCP)(HOST = {2})(PORT = {3}))(CONNECT_DATA =(SID = {4})));User Id={0};Password{1};",
           user,
           pword,
           host,
           port,
           serviceName
           );
    }
}

И тип данных для столбца FILE_CONTENTS был BLOB, FILE_SIZE был NUMBER(10,0), LAST_MODIFIED был DATE, а остальные были NVARCHAR2(250).

1
ответ дан vapcguy 28 August 2018 в 10:57
поделиться
Другие вопросы по тегам:

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