c# - किसी भी फाइल को डेटाबेस में सहेजना, बस इसे बाइट सरणी में परिवर्तित करें?




file-io byte (5)

किसी फ़ाइल को डिस्क या डेटाबेस var बाइनरी कॉलम में सहेजने के लिए किसी बाइट सरणी में फ़ाइल को कनवर्ट करना सबसे अच्छा तरीका है?

तो अगर कोई .gif या .doc / .docx या .pdf फ़ाइल को सहेजना चाहता है, तो क्या मैं इसे केवल एक बाइटरीयर UFT8 में परिवर्तित कर सकता हूं और इसे बाइट्स की धारा के रूप में डीबी में सहेज सकता हूं?


आप किस डेटाबेस का उपयोग कर रहे हैं? आमतौर पर आप फ़ाइलों को डेटाबेस में सहेजते नहीं हैं लेकिन मुझे लगता है कि एसक्यूएल 2008 के लिए इसका समर्थन है ...

एक फ़ाइल द्विआधारी डेटा है इसलिए यूटीएफ 8 कोई फर्क नहीं पड़ता ..

यूटीएफ 8 मायने रखता है जब आप स्ट्रिंग को बाइट सरणी में कनवर्ट करने का प्रयास करते हैं ... बाइट सरणी में फ़ाइल नहीं।


चूंकि यह उल्लेख नहीं किया गया है कि आपके डेटाबेस का क्या मतलब है मैं SQL सर्वर मान रहा हूं। नीचे 2005 और 2008 दोनों के लिए समाधान काम करता है।

आपको कॉलम में से एक के रूप में VARBINARY(MAX) साथ तालिका बनाना है। मेरे उदाहरण में मैंने कॉलम RaportPlik को VARBINARY(MAX) कॉलम के साथ टेबल Raporty बनाई है।

drive से डेटाबेस में file डालने का तरीका :

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 पर सहेजने के 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;
    }

हैप्पी कोडिंग :-)


पुष्टि करते हुए कि मैं मैडबॉय द्वारा पोस्ट किए गए उत्तर का उपयोग करने और वर्चुअल (MAX) कॉलम का उपयोग करके सूचीबद्ध संस्करणों के अलावा एमएस एसक्यूएल सर्वर 2012 और 2014 दोनों पर ओटील द्वारा संपादित किया गया था।

यदि आप सोच रहे हैं कि क्यों आप 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 (अधिकतम) कॉलम को जोड़ा जा सकता है:

वैकल्पिक तालिका तालिका नाम

कॉलमनाम वर्बिनरी (अधिकतम) FILESTREAM नल जोड़ें

चले जाओ


मैं SQL सर्वर और ओरेकल में फ़ाइलों को संग्रहीत करने के तरीके का वर्णन करूंगा। यह काफी हद तक इस बात पर निर्भर करता है कि आप फ़ाइल को कैसे प्राप्त कर रहे हैं, इस बारे में कि आप इसकी सामग्री कैसे प्राप्त करेंगे, और यह इस बात पर निर्भर करता है कि आप किस सामग्री का उपयोग कर रहे हैं उस सामग्री के लिए जिसमें आप इसे स्टोर करेंगे, इसे स्टोर करने के लिए आप इसे स्टोर करेंगे। ये 2 अलग-अलग डेटाबेस उदाहरण हैं जिनकी फाइल मैंने उपयोग की 2 अलग-अलग विधियों के साथ की है।

एस क्यू एल सर्वर

संक्षिप्त उत्तर: मैंने बेस 64 बाइट स्ट्रिंग का उपयोग किया जिसे मैंने एक byte[] परिवर्तित किया और एक varbinary(max) फ़ील्ड में स्टोर किया।

लंबा जवाब:

मान लें कि आप किसी वेबसाइट के माध्यम से अपलोड कर रहे हैं, इसलिए आप एक <input id="myFileControl" type="file" /> नियंत्रण, या ड्रॉप ड्रॉपज़ोन का उपयोग कर रहे हैं। फ़ाइल प्राप्त करने के लिए, आप var myFile = document.getElementById("myFileControl")[0]; तरह कुछ कर रहे हैं var myFile = document.getElementById("myFileControl")[0]; या myFile = this.state.files[0];

वहां से, मुझे कोड का उपयोग कर बेस 64 स्ट्रिंग मिल जाएगी: इनपुट = फ़ाइल को बाइट सरणी में कनवर्ट करें (फ़ंक्शन UploadFile2 उपयोग करें)।

तब मुझे उस स्ट्रिंग, फ़ाइल नाम ( myFile.name ) और टाइप ( myFile.type ) को JSON ऑब्जेक्ट में प्राप्त होगा:

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

और XMLHttpRequest का उपयोग करके फ़ाइल को एक एमवीसी सर्वर बैकएंड पर पोस्ट करें, एक सामग्री-प्रकार का application/json xhr.send(JSON.stringify(myJSONObj); निर्दिष्ट करें: xhr.send(JSON.stringify(myJSONObj); आपको इसे देखने के लिए xhr.send(JSON.stringify(myJSONObj); बनाना होगा:

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)

फिर आप इसे उस फ़ंक्शन में जोड़ सकते हैं और इसे इकाई फ्रेमवर्क का उपयोग करके सहेज सकते हैं:

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 कॉलम और MY_ATTACHMENT_TABLE_MODEL रूप में public int Size { get; set;} रूप में जोड़कर आकार शामिल कर सकते हैं public int Size { get; set;} public int Size { get; set;} , और लाइन tblAtchm.Size = System.Convert.FromBase64String(myModelObj.file).Length; ऊपर।

आकाशवाणी

संक्षिप्त उत्तर: इसे byte[] परिवर्तित करें byte[] , इसे OracleParameter को असाइन करें, इसे अपने OracleParameter में जोड़ें, और पैरामीटर के ParameterName मान के संदर्भ में अपनी तालिका के BLOB फ़ील्ड को अपडेट करें :BlobParameter

लंबा जवाब: जब मैंने ओरेकल के लिए ऐसा किया, तो मैं एक 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);
}

और ओरेकल अपडेट के अंदर, एडीओ के साथ किया गया:

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)


हां, आमतौर पर डेटाबेस में फ़ाइल को स्टोर करने का सबसे अच्छा तरीका है BLOB कॉलम में बाइट सरणी को सहेजना। आप शायद कुछ स्तंभों को फ़ाइल के मेटाडेटा जैसे नाम, एक्सटेंशन आदि को स्टोर करने के लिए चाहते हैं।

डेटाबेस में फ़ाइलों को स्टोर करना हमेशा अच्छा विचार नहीं है - उदाहरण के लिए, यदि आप इसमें फ़ाइलों को संग्रहीत करते हैं तो डेटाबेस आकार तेज़ी से बढ़ेगा। लेकिन यह सब आपके उपयोग परिदृश्य पर निर्भर करता है।





byte