Enregistrer un fichier dans la firebase database, convertissez-le en un tableau d’octets?

Est-ce que la conversion d’un fichier en un tableau d’octets est la meilleure façon d’enregistrer le format de fichier ANY sur le disque ou la firebase database var binary column?

Donc, si quelqu’un veut enregistrer un fichier .gif ou .doc / .docx ou .pdf, est-ce que je peux le convertir en un bytearray UFT8 et l’enregistrer sur la firebase database sous forme de stream d’octets?

Comme il n’est pas mentionné quelle firebase database vous voulez dire, je suppose que SQL Server. La solution ci-dessous fonctionne pour 2005 et 2008.

Vous devez créer une table avec VARBINARY(MAX) comme l’une des colonnes. Dans mon exemple, j’ai créé la Table Raporty avec la colonne RaportPlik colonne VARBINARY(MAX) .

Méthode pour placer le file dans la firebase database à partir du drive :

 public static void databaseFilePut(ssortingng 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(); } } 

Cette méthode consiste à récupérer le file de la firebase database et à l’enregistrer sur le drive :

 public static void databaseFileRead(ssortingng varID, ssortingng 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); } } } 

Cette méthode consiste à récupérer le file de la firebase database et à le mettre en MemoryStream :

 public static MemoryStream databaseFileRead(ssortingng 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; } 

Cette méthode consiste à mettre MemoryStream dans la firebase database:

 public static int databaseFilePut(MemoryStream fileToPut) { int varID = 0; byte[] file = fileToPut.ToArray(); const ssortingng 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; } 

Heureux codage 🙂

Bien que vous puissiez stocker des fichiers de cette manière, les compromis sont importants:

  • La plupart des bases de données ne sont pas optimisées pour des quantités géantes de données binarys, et les performances des requêtes se dégradent souvent de manière spectaculaire à mesure que la table se gonfle, même avec des index. (SQL Server 2008, avec le type de colonne FILESTREAM, est l’exception à la règle.)
  • La sauvegarde / réplication de firebase database devient extrêmement lente.
  • Il est beaucoup plus facile de gérer un lecteur corrompu avec 2 millions d’images – il suffit de remplacer le disque sur le RAID – par rapport à une table de firebase database corrompue.
  • Si vous supprimez accidentellement une douzaine d’images sur un système de fichiers, vos opérations peuvent les remplacer assez facilement à partir d’une sauvegarde, et comme l’index de la table est infime en comparaison, il peut être restauré rapidement. Si vous supprimez accidentellement une douzaine d’images dans une table de firebase database géante, l’attente pour restaurer la firebase database à partir de la sauvegarde est longue et pénible, ce qui paralyse l’intégralité de votre système entre-temps.

Ce ne sont là que quelques-uns des inconvénients que je peux imaginer. Pour les projets de petite taille, il peut être intéressant de stocker des fichiers de cette manière, mais si vous concevez des logiciels de niveau professionnel, je vous le déconseille fortement.

Cela dépend vraiment du serveur de firebase database.

Par exemple, SQL Server 2008 prend en charge un type de données FILESTREAM pour cette situation.

En dehors de cela, si vous utilisez un MemoryStream , il a une méthode ToArray() qui sera convertie en un byte[] – cela peut être utilisé pour varbinary un champ varbinary .

Confirmant que j’ai pu utiliser la réponse publiée par MadBoy et éditée par Otiel sur MS SQL Server 2012 et 2014 en plus des versions précédemment répertoriées utilisant des colonnes varbinary (MAX).

Si vous vous demandez pourquoi vous ne pouvez pas “Filestream” (noté dans une réponse séparée) en tant que type de données dans le concepteur de tables SQL Server ou pourquoi vous ne pouvez pas définir le type de données d’une colonne sur “Filestream” en utilisant T-SQL, atsortingbut du type de données varbinary (MAX). Ce n’est pas un type de données en soi.

Consultez ces articles sur la configuration et l’activation de FILESTREAM sur une firebase database: 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

Une fois configurée, une colonne varbinary (max) activée pour filestream peut être ajoutée comme suit:

ALTER TABLE TableName

ADD ColumnName varbinary (max) FILESTREAM NULL

ALLER

Quelle firebase database utilisez-vous? Normalement, vous ne sauvegardez pas les fichiers dans une firebase database, mais je pense que sql 2008 a le support pour cela …

Un fichier est une donnée binary, donc UTF 8 n’a pas d’importance ici.

UTF 8 est important lorsque vous essayez de convertir une chaîne en un tableau d’octets … et non un tableau en octets.

Je décrirai la manière dont j’ai stocké les fichiers dans SQL Server et Oracle. Cela dépend en grande partie de la façon dont vous obtenez le fichier, en premier lieu, de la manière dont vous allez obtenir son contenu, et cela dépend de la firebase database que vous utilisez pour le contenu dans lequel vous allez le stocker. Ce sont 2 exemples de bases de données séparés avec 2 méthodes distinctes pour obtenir le fichier que j’ai utilisé.

serveur SQL

Réponse courte: J’ai utilisé une chaîne d’octets base64 convertie en byte[] et varbinary(max) dans un varbinary(max) .

Longue réponse:

Supposons que vous téléchargez via un site Web, vous utilisez donc un contrôle ou React DropZone. Pour obtenir le fichier, vous faites quelque chose comme var myFile = document.getElementById("myFileControl")[0]; ou myFile = this.state.files[0]; .

De là, j’obtiens la chaîne base64 en utilisant le code ici: Convertir input = file en tableau d’octets (utilisez la fonction UploadFile2 ).

Ensuite, j’obtiendrais cette chaîne, le nom du fichier ( myFile.name ) et tapez ( myFile.type ) dans un object JSON:

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

et publier le fichier sur un serveur principal MVC à l’aide de XMLHttpRequest, en spécifiant un Content-Type d’ application/json : xhr.send(JSON.ssortingngify(myJSONObj); Vous devez créer un ViewModel pour le lier à:

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

et spécifiez [FromBody]MyModel myModelObj tant que paramètre transmis:

 [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) 

Ensuite, vous pouvez append ceci dans cette fonction et l’enregistrer en utilisant Entity Framework:

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

tblAtchm.File = System.Convert.FromBase64Ssortingng(myModelObj.file); être la ligne opératoire.

Vous auriez besoin d’un modèle pour représenter la table de firebase database:

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

Cela sauvegardera les données dans un varbinary(max) sous la byte[] un byte[] . Name et Type étaient respectivement nvarchar(250) et nvarchar(10) . Vous pouvez inclure la taille en l’ajoutant à votre table en tant que colonne int & MY_ATTACHMENT_TABLE_MODEL tant que public int Size { get; set;} public int Size { get; set;} , et ajoutez la ligne tblAtchm.Size = System.Convert.FromBase64Ssortingng(myModelObj.file).Length; au dessus.

Oracle

Réponse courte: Convertissez-le en un byte[] , assignez-le à un OracleParameter , ajoutez-le à votre OracleCommand et mettez à jour le champ BLOB votre table en utilisant une référence à la valeur ParameterName du ParameterName :BlobParameter

Réponse longue: Quand je l’ai fait pour Oracle, j’utilisais OpenFileDialog et j’ai récupéré et envoyé les informations sur les octets / fichiers de la manière suivante:

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

Et dans la mise à jour Oracle, faite avec ADO:

 public void RunCommand(ssortingng sql, OracleParameter param) { OracleConnection oraConn = null; OracleCommand oraCmd = null; try { ssortingng connSsortingng = GetConnSsortingng(); oraConn = OracleConnection(connSsortingng); 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 ssortingng GetConnSsortingng() { ssortingng host = System.Configuration.ConfigurationManager.AppSettings["host"].ToSsortingng(); ssortingng port = System.Configuration.ConfigurationManager.AppSettings["port"].ToSsortingng(); ssortingng serviceName = System.Configuration.ConfigurationManager.AppSettings["svcName"].ToSsortingng(); ssortingng schemaName = System.Configuration.ConfigurationManager.AppSettings["schemaName"].ToSsortingng(); ssortingng pword = System.Configuration.ConfigurationManager.AppSettings["pword"].ToSsortingng(); // hopefully encrypted if (Ssortingng.IsNullOrEmpty(host) || Ssortingng.IsNullOrEmpty(port) || Ssortingng.IsNullOrEmpty(serviceName) || Ssortingng.IsNullOrEmpty(schemaName) || Ssortingng.IsNullOrEmpty(pword)) { return "Missing Param"; } else { pword = decodePassword(pword); // decrypt here return Ssortingng.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 ); } } 

Et le type de données pour la colonne FILE_CONTENTS était BLOB , le FILE_SIZE était NUMBER(10,0) , LAST_MODIFIED était DATE et les autres étaient NVARCHAR2(250) .

Oui, le meilleur moyen de stocker un fichier dans une firebase database consiste généralement à enregistrer le tableau d’octets dans une colonne BLOB. Vous souhaiterez probablement que deux colonnes stockent en plus les métadonnées du fichier, telles que le nom, l’extension, etc.

Il n’est pas toujours judicieux de stocker des fichiers dans la firebase database – par exemple, la taille de la firebase database augmentera rapidement si vous y stockez des fichiers. Mais tout dépend de votre scénario d’utilisation.