데이터베이스에 파일을 저장하고 바이트 배열로 변환 하시겠습니까?
파일을 바이트 배열로 변환하는 것이 모든 파일 형식을 디스크 또는 데이터베이스 var 바이너리 열에 저장하는 가장 좋은 방법입니까?
그래서 누군가가 .gif, .doc / .docx 또는 .pdf 파일을 저장하고 싶다면, bytearray UFT8로 변환하고 db에 바이트 스트림으로 저장할 수 있습니까?
어떤 데이터베이스를 의미하는지 언급되지 않았기 때문에 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;
}
해피 코딩 :-)
이 방식으로 파일을 저장할 수 있지만 상당한 장단점이 있습니다.
- 대부분의 DB는 방대한 양의 이진 데이터에 최적화되어 있지 않으며 인덱스가 있더라도 테이블이 팽창하면 쿼리 성능이 크게 저하되는 경우가 많습니다. (FILESTREAM 열 유형을 사용하는 SQL Server 2008은 규칙에 대한 예외입니다.)
- DB 백업 / 복제가 매우 느려집니다.
- 손상된 DB 테이블보다 2 백만 개의 이미지가있는 손상된 드라이브를 처리하는 것이 훨씬 쉽습니다. RAID의 디스크 만 교체하면됩니다.
- 실수로 파일 시스템에서 12 개의 이미지를 삭제하면 운영 담당자가 백업에서 이미지를 매우 쉽게 교체 할 수 있으며, 테이블 인덱스가 비교적 작기 때문에 빠르게 복원 할 수 있습니다. 거대한 데이터베이스 테이블에서 실수로 12 개의 이미지를 삭제하면 백업에서 DB를 복원하는 데 오래 걸리고 고통스럽고 그 동안 전체 시스템이 마비됩니다.
이것들은 내가 생각할 수있는 몇 가지 단점 일 뿐이다. 작은 프로젝트의 경우 이러한 방식으로 파일을 저장할 가치가있을 수 있지만 엔터프라이즈 급 소프트웨어를 설계하는 경우에는 사용하지 않는 것이 좋습니다.
실제로 데이터베이스 서버에 따라 다릅니다.
예를 들어 SQL Server 2008은 FILESTREAM
정확히이 상황에 대한 데이터 형식을 지원합니다 .
그 외에를 사용하면 a 로 변환 MemoryStream
되는 ToArray()
메서드가 byte[]
있습니다. varbinary
필드 를 채우는 데 사용할 수 있습니다 .
예, 일반적으로 데이터베이스에 파일을 저장하는 가장 좋은 방법은 BLOB 열에 바이트 배열을 저장하는 것입니다. 이름, 확장자 등과 같은 파일의 메타 데이터를 추가로 저장하기 위해 몇 개의 열이 필요할 것입니다.
데이터베이스에 파일을 저장하는 것이 항상 좋은 생각은 아닙니다. 예를 들어 파일을 저장하면 데이터베이스 크기가 빠르게 커집니다. 그러나 그것은 모두 사용 시나리오에 달려 있습니다.
이전에 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
일단 구성되면 filestream 사용 varbinary (max) 열을 다음과 같이 추가 할 수 있습니다.
ALTER TABLE TableName
ADD ColumnName varbinary (max) FILESTREAM NULL
가다
SQL Server와 Oracle에서 파일을 저장 한 방법을 설명하겠습니다. 그것은 주로 파일을 어떻게 얻는 지, 어떻게 그 내용을 얻을 것인지에 달려 있으며, 그것을 저장하는 방법을 위해 그것을 저장할 내용에 대해 어떤 데이터베이스를 사용하는지에 달려 있습니다. 다음은 내가 사용한 파일을 가져 오는 두 가지 별도의 방법이있는 두 개의 별도 데이터베이스 예제입니다.
SQL 서버
짧은 대답 : 저는 a로 변환 byte[]
하고 varbinary(max)
필드에 저장 하는 base64 바이트 문자열을 사용했습니다 .
긴 대답 :
웹 사이트를 통해 업로드하고 있으므로 <input id="myFileControl" type="file" />
컨트롤 또는 React DropZone을 사용하고 있다고 가정 해 보겠습니다. 파일을 얻으려면 var myFile = document.getElementById("myFileControl")[0];
또는 같은 작업을 수행합니다 myFile = this.state.files[0];
.
여기에서 코드를 사용하여 base64 문자열을 얻습니다. Convert input = file to byte array (use function UploadFile2
).
그런 다음 해당 문자열, 파일 이름 ( myFile.name
) 및 유형 ( myFile.type
)을 JSON 개체에 가져옵니다.
var myJSONObj = {
file: base64string,
name: myFile.name,
type: myFile.type,
}
XMLHttpRequest를 사용하여 파일을 MVC 서버 백엔드에 게시하고 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
열 및 MY_ATTACHMENT_TABLE_MODEL
으로 public int Size { get; set;}
추가하고 tblAtchm.Size = System.Convert.FromBase64String(myModelObj.file).Length;
위 의 줄 에 추가하여 크기를 포함 할 수 있습니다 .
신탁
간단한 대답 :로 변환하고에 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
);
}
}
And the datatype for the FILE_CONTENTS
column was BLOB
, the FILE_SIZE
was NUMBER(10,0)
, LAST_MODIFIED
was DATE
, and the rest were NVARCHAR2(250)
.
What database are you using? normally you don't save files to a database but i think sql 2008 has support for it...
A file is binary data hence UTF 8 does not matter here..
UTF 8 matters when you try to convert a string to a byte array... not a file to byte array.
'Development Tip' 카테고리의 다른 글
Visual Studio Code에서 자동 완성 방지 (0) | 2020.11.16 |
---|---|
ASP.NET 유효성 검사기로 날짜 유효성 검사 (0) | 2020.11.16 |
Xcode 4에서 .xcconfig 파일을 어떻게 사용할 수 있습니까? (0) | 2020.11.16 |
Javascript에서 배열에 중복 값이 있는지 어떻게 확인합니까? (0) | 2020.11.16 |
인 텐트를 통해 SMS 보내기 (0) | 2020.11.16 |