[Django][RestAPI] Image Path로 서버에 이미지 업로드하기
서버에서는 사용자 PC에 있는 이미지의 경로만 갖고 해당 위치의 이미지를 서버로 복사(이동)할 수 없다.
파일 열기(불러오기)기능을 하는 <input type="file">
을 이용하면 가능하지만, JS에서 서버로 넘긴 path만으로는 Chrome에서 사용자 PC에 접근을 막았기(fakepath, Chrome보안정책) 때문에 불가능했다.
Electron(NodeJS)에서 서버로 RestAPI(Django Rest FrameWork)를 통해서 이미지 경로만 갖고 여러 개의 이미지를 한번에 전송하려면 base64로 인코딩(encode/encoding)한 값을 서버로 전달 한 후 서버에서 base64를 이미지로 디코딩(decode/decoding)해주면 된다.
먼저, Electron에서 path에 존재하는 이미지를 base64로 인코딩 해준다.
(아래 예제에서는 Client에서 base64변환 후 Main에서 Rest API로 전달했지만, Main에서 모두 처리해도 상관은 없다.)
-
Electron Client 부분
const { ipcRenderer, remote } = require('electron') const fs = require('fs') const filepath = "C:\Users\user\images\aaa.png" // 변환 function base64_encode(file) { let buf = fs.readFileSync(file); let base64 = buf.toString('base64'); return base64; }; const _base64 = base64_encode(filepath) ipcRenderer.sendSync('sPOST', _base64)
-
Electron MainProcess 부분
// index.js const { ipcMain } = require("electron"); // ...생략... ipcMain.on("sPOST", async (event, data) => { event.returnValue = await post(data) }) function post(data) { return new Promise(function (resolve, reject) { const _URL = `http://127.0.0.1:8000/image/` const data = Object.assign({ headers: { 'Content-type': 'application/json', }, }, param) axios.post(_URL, data).then((response) => { if (response.status === 201) { // created = 201 resolve(response.data) } else resolve(false) }) .catch((error) => { console.log(error) resolve(false) }); }) }
Django Rest API에서 사용할 모델(Model)을 아래와 같이 간단하게 선언했다.
Django에서 Image관련 Field를 제공한다.
* ImageField
- ImageField를 사용하려면 settings.py에 MEDIA_ROOT를 정의해야 한다.
- https://docs.djangoproject.com/ko/2.2/faq/usage/#how-do-i-use-image-and-file-fields
# models.py
from __future__ import unicode_literals
from django.db import models
from django_mysql.models import Model
class Image(models.Model):
name = models.CharField(max_length=500, primary_key=True) # 파일명
image = models.ImageField(upload_to='uploads', blank=True) # 이미지
base64 = models.TextField(blank=True) # base64
마지막으로, base64를 Image로 변환(디코딩)하는 부분을 serializers.py
에 선언했다.
# serializers.py
from rest_framework import serializers
from .models import Image
from django.core.files.base import ContentFile
import uuid
import base64
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = Image
fields = '__all__'
def create(self, validated_data):
image_name = str(uuid.uuid4()) # image name 생성
# 있으면 업데이트 없으면 생성
result, created = FileList.objects.get_or_create(
name=image_name,
base64=validated_data.get('base64', None), # base64
image=ContentFile(base64.b64decode(validated_data.get('base64', None)), name=image_name + '.png') # Image
)
return result
'Python > Django' 카테고리의 다른 글
[Django][React] Django와 React 설정하기 (0) | 2019.08.01 |
---|---|
[Django] Django Rest API 특정 필드 제외하고 검색하기 (0) | 2019.07.31 |
[Django] static 파일 불러오기 (0) | 2019.07.01 |
[Django] Vue.js 사용하기 (1) | 2019.06.05 |
[Django] Database 테이블에 데이터가 없을 때 만 추가하는 방법 (0) | 2019.01.31 |