ファイルをバイト配列に変換することが、ディスクまたはデータベースのvarバイナリ列に任意のファイル形式を保存する最良の方法ですか?
だから誰かが.gifまたは.doc/.docxまたは.pdfファイルを保存したい場合、それをbytearray UFT8に変換し、バイトストリームとしてdbに保存できますか?
SQL Serverを想定しているので、どのデータベースを意味するのかについては触れていません。以下のソリューションは2005年と2008年の両方で機能します。
列の1つとしてVARBINARY(MAX)
を使用してテーブルを作成する必要があります。この例では、列Raporty
がVARBINARY(MAX)
列であるテーブルRaportPlik
を作成しました。
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;
}
ハッピーコーディング:-)
この方法でファイルを保存できますが、大きなトレードオフがあります。
これらは、頭の外から思いつくことができる欠点のほんの一部です。小さなプロジェクトの場合は、この方法でファイルを保存する価値がありますが、エンタープライズグレードのソフトウェアを設計している場合は、それを強くお勧めします。
本当にデータベースサーバーに依存します。
たとえば、SQL Server 2008は、まさにこの状況のために FILESTREAM
データ型をサポートしています。
それ以外に、MemoryStream
を使用する場合、byte[]
に変換する ToArray()
メソッドがあります。これは、varbinary
フィールドの設定に使用できます。
Varbinary(MAX)列を使用して以前にリストされたバージョンに加えて、MadBoyによって投稿され、Otielによって編集された回答をMS SQL Server 2012と2014の両方で使用できることを確認しました。
SQL Serverテーブルデザイナでデータ型として「Filestream」(別の回答に記載)できないのか、T-SQLを使用して列のデータ型を「Filestream」に設定できないのか疑問に思う場合は、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 TABLETableName
ADDColumnNamevarbinary(max)FILESTREAM NULL
行く
SQL ServerとOracleでのファイルの保存方法について説明します。そもそも、ファイルを取得する方法、その内容を取得する方法に大きく依存します。また、ファイルを保存するコンテンツのために使用しているデータベースに依存します。これらは、私が使用したファイルを取得する2つの異なる方法を備えた2つの異なるデータベースの例です。
SQL Server
簡単な答え:byte[]
に変換してvarbinary(max)
フィールドに保存するbase64バイト文字列を使用しました。
長い答え:
Webサイト経由でアップロードしているので、<input id="myFileControl" type="file" />
コントロール、またはReact DropZoneを使用しているとします。ファイルを取得するには、var myFile = document.getElementById("myFileControl")[0];
またはmyFile = this.state.files[0];
などの操作を行っています。
そこから、次のコードを使用してbase64文字列を取得します。 入力=ファイルをバイト配列に変換 (関数UploadFile2
を使用)。
次に、その文字列、ファイル名(myFile.name
)を取得し、JSONオブジェクトにタイプ(myFile.type
)を入力します。
var myJSONObj = {
file: base64string,
name: myFile.name,
type: myFile.type,
}
xMLHttpRequestを使用してMVCサーバーバックエンドにファイルを投稿し、application/json
:xhr.send(JSON.stringify(myJSONObj);
のContent-Typeを指定します。次とバインドする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
列としてサイズを追加し、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);
}
そして、ADOを使用して行われるOracleの更新内:
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列に保存することです。名前、拡張子などのファイルのメタデータを追加で格納するために、おそらくいくつかの列が必要になります。
データベースにファイルを保存することは常に良い考えではありません-たとえば、ファイルを保存するとデータベースのサイズは急速に大きくなります。しかし、それはすべて使用シナリオに依存します。
どのデータベースを使用していますか?通常、データベースにファイルを保存しませんが、SQL 2008はそれをサポートしていると思います...
ファイルはバイナリデータであるため、ここではUTF 8は重要ではありません。
UTF 8は、文字列をバイト配列に変換しようとするときに重要になります。ファイルからバイト配列への変換ではありません。