개요
검색 결과 페이지에서 레시피의 다운로드 버튼을 클릭하면 받을 수 있는 압축 파일을 만들 것이다. 압축 파일에는 레시피 이미지 파일과 레시피 title, ingredients, instructions 가 포함된 .txt 파일을 포함한다. 이 압축 파일은 이미지 image_file 컬럼 처럼 recipe_zip_file 이라는 새 컬럼을 만들어 바이너리 데이터로 DB에 삽입한다.
DB 컬럼 추가 및 데이터 삭제
-- 값이 누락된 데이터 삭제
DELETE *
FROM tb_recipe
WHERE title = ''
OR ingredients = '[]'
OR instructions = ''
OR image_name = '';
-- 손상된 이미지 파일의 레코드 삭제 (파일은 존재하지만 손상된 파일)
DELETE
FROM tb_recipe
WHERE id = 9894;
먼저 recipe_zip_file 이라는 BLOB 타입의 컬럼을 추가한다. 이후 image_file 과 같이 그냥 로직을 실행시키면, 에러가 발생하기 때문에 알맞지 않은 DB 데이터를 한 번 삭제한다.
압축 파일 생성 및 DB 삽입
//compress_binary.js
const path = require('path');
const fs = require('fs');
const archiver = require('archiver');
export default class CompressBinary {
db = null;
constructor(db) {
this.db = db;
}
async InsertBinaryToSqliteDB() {
const maxId = this.db.selectMaxId()[0].max_id;
console.log('maxId: ' + maxId);
let id = 0;
while(id <= maxId) {
let recipe = this.db.selectRecipeById(id)[0];
if (recipe === undefined) {
console.log('This is undefined.');
id++;
continue;
}
let title = recipe.title;
let ingredients = recipe.ingredients.replace(/""/g, '"');
let matchArray = ingredients.match(/'[^']*'|"[^"]*"/g);
let ingredientsArray = matchArray.map(match => match.slice(1, -1));
let instructions = recipe.instructions;
let imageName = recipe.image_name;
let txtString = `Title: ${title} `;
txtString += `\\n\\nIngredients: `;
ingredientsArray.forEach(function(ingredient) {
txtString += `\\n* ${ingredient}`;
});
txtString += `\\n\\nInstrunctions: \\n${instructions}`;
let txtData = Buffer.from(txtString, 'utf-8');
let imagePath = 'D://db/recipe db/Food Images/' + imageName + '.jpg';
let zipBuffer;
let archive = archiver('zip', { zlib: { level: 9 } });
archive.append(txtData, { name: title + '_recipe.txt' });
archive.file(imagePath, { name: imageName + '.jpg' });
await this.finalizeArchive(archive);
zipBuffer = archive.read();
this.db.updateRecipeZipFileById(zipBuffer, id);
console.log(title + ' is completed.');
/*
let zipPath = 'D://db/recipe db/recipe zip/'+title+'.zip';
fs.writeFile(zipPath, zipBuffer, 'binary', function(err) {
if (err) {
console.log('Fail !! ');
} else {
console.log('File written successfully: ' + zipPath);
}
});
*/
id++;
}
}
async finalizeArchive(archive) {
return new Promise((resolve, reject) => {
archive.on('finish', resolve);
archive.on('error', reject);
archive.finalize();
});
}
}
//main.js
.
.
.
import RcpSqliteDB from "../rcp_sqlite_db";
import CompressBinary from "./binary/compress_binary";
.
.
.
const createWindow = () => {
.
.
.
mainWindow.once('ready-to-show', () => {
.
.
.
//db open
let db = new RcpSqliteDB();
db.open();
.
.
.
let compressBinary = new CompressBinary(db);
compressBinary.InsertBinaryToSqliteDB();
});
.
.
.
};
이후 CompressBinary 클래스를 작성하여 ImageBinary 클래스와 유사하게 사용한다.
- MaxId를 조회하고 그 수 만큼 반복시킨다.
- id로 레코드를 조회하여 각 컬럼 값을 알맞게 파싱하여 문자열로 만든 후 Buffer 타입으로 변환시켜 저장한다. (.txt)
- image_name 컬럼 값으로 이미지 파일의 경로를 구한다.
- 압축 파일이 될 archiver를 선언하고, 문자열 buffer 값(txtData)과 이미지 파일을 알맞은 이름을 압축 파일(archiver)에 추가한다.
- 압축 파일을 buffer 타입으로 저장한다.
- 변환된 binary 데이터는 DB의 BLOB 컬럼에 저장된다.
'토이 프로젝트 > 레시피 일렉트론 앱 (완)' 카테고리의 다른 글
[Electron] 7.검색 기능 구현(1): 검색 결과 및 페이징 - 레시피 일렉트론 앱 (1) | 2024.01.28 |
---|---|
[Electron] 6.프로세스와 IPC 통신 - 레시피 일렉트론 앱 (1) | 2024.01.23 |
[Electron] 4.이미지 바이너리화 - 레시피 일렉트론 앱 (0) | 2024.01.20 |
[Electron] 3.Electron 프로젝트 생성 - 레시피 일렉트론 앱 (0) | 2024.01.19 |
[Electron] 2.Sqlite3 DB Fts5 설계 - 레시피 일렉트론 앱 (1) | 2024.01.18 |