Так как не упоминается какая база данных вы подразумеваете, я предполагаю 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;
}
Счастливое кодирование: -)
Подтверждение того, что я смог использовать ответ, отправленный 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
Несмотря на то, что вы можете хранить файлы таким образом, у него есть значительные компромиссы:
Это всего лишь некоторые из недостатков я могу подняться с головы. Для небольших проектов, возможно, стоит хранить файлы таким образом, но если вы разрабатываете программное обеспечение корпоративного уровня, я бы настоятельно рекомендовал против него.
Да, обычно лучший способ сохранить файл в базе данных - сохранить массив байтов в столбце BLOB. Вероятно, вам понадобится несколько столбцов для хранения метаданных файла, таких как имя, расширение и т. Д.
Не всегда хорошая идея хранить файлы в базе данных - например, в базе данных размер будет быстро расти, если вы храните в нем файлы. Но все зависит от вашего сценария использования.
Это действительно зависит от сервера базы данных.
Например, SQL Server 2008 поддерживает тип данных FILESTREAM
для этой ситуации.
Другое чем это, если вы используете MemoryStream
, у него есть метод ToArray()
, который преобразуется в byte[]
- это может использоваться для заполнения поля varbinary
..
Какую базу данных вы используете? обычно вы не сохраняете файлы в базе данных, но я думаю, что sql 2008 поддерживает его ...
Файл представляет собой двоичные данные, поэтому UTF 8 здесь не имеет значения.
UTF 8 имеет значение, когда вы пытаетесь преобразовать строку в массив байтов ... не файл в байтовый массив.
Я опишу способ хранения файлов в 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)
.