8 글 보임 - 1 에서 8 까지 (총 8 중에서)
-
글쓴이글
-
2023년 9월 8일 13:42 #97302
정중식참가자선생님 안녕하신가요! react-quill에서 이미지 처리에대해서 골치를썩고있습니다. <ReactQuill ref={quillRef} modules={modules} theme='snow' value={contents} onChange={setContents} placeholder='여기에 내용을 입력하세요...' /> 코드를보면 conents를 콘솔에 찍으면 <p>안녕하세요 <br/>
</p> 이런식으로 들어가는데요 문제는 img src='엄청길게 들어감' 이 문제입니다. contents에 꼭 img를 담아서 서버에 보내줘야하나요? (img안담을수있는 방법으로는 이미지핸들러를 따로 코드작성해서 뭐 서버에 file보내서 aws s3 url 방식으로 하면 되는데 제가원하는 방식은 글올리기를 눌러야 aws s3에 올라가는 방식을 원함) 선생님 코딩애플 사이트는 어떻게 처리해주셧나요? 제가 원하는 동작방식은 이겁니다. 1. aws s3에 이미지 업로드 (글 올리기버튼을 눌르면 aws s3에 이미지 업로드 되게끔) 2. contents에는 img안들어가고 텍스트만 들어가게 설정 3. react-quill에디터(지금 글쓰고있는 이곳)에 이미지가 뜨고 이미지 리사이징 할 수 있을것 어떤식으로 접근해야할까요..
2023년 9월 8일 18:30 #97343
정중식참가자선생님 제 나름대로 시도해본건 1. 처음 이미지 업로드 함수 2. 이미지 크기 수정 함수 이렇게 두개를 나눴습니다. 나눈 이유는 선생님이 react-quill을 사용해보셨는지는 모르겠지만
const { attributes, insert } = editorContent.ops[0];
여기서 console.log(attributes); 를해보면 언디파인이뜹니다. 근데, 이미지 크기를 한번이라도 수정을 해주면 width:'이미지가로넓이'px 이렇게뜹니다. 그래서 1번과 2번으로 나눴는데요 문제는.. 처음 이미지 함수에서 이미지를 올린것과 이미지 크기 수정함수에서 이미지를 수정하면 같은 이미지면 중복해서 저장이되어야하는데 각각 저장이 되어버립니다.. 저장되어있는 (status[]) 배열에 이미지가 중복해있으면 그 이미지를 덮어쓰게끔 해주고싶은데 .. 너무 복잡하게 구현하고있는걸까요?
혹시몰라서 제 전체 코드 첨부했습니다..
import React, { FormEvent, useMemo, useRef, useState } from 'react'; import ReactQuill, { Quill } from 'react-quill'; import { base64StringToBlob } from 'blob-util'; import { ImageResize } from 'quill-image-resize-module-ts'; import 'react-quill/dist/quill.snow.css'; import { useLocation } from 'react-router-dom'; import { styled } from 'styled-components';
Quill.register('modules/imageResize', ImageResize);
const Container = styled.div` .quill { .ql-editor { min-height: 20rem; height: 100%; }</pre> <pre> .ql-snow { border: 1px solid #eee; } .ql-container { min-height: 20rem; height: 100%; /* height: 10rem; */ /* height: 20rem; */ } } `;
const Button = styled.button<{ bgColor: string }>` width: 100%; padding: 0.5rem; margin: 0.5rem 0; border-radius: 5px; border: 1px solid #eee; font-weight: bold; transition: all 0.3s ease; &:hover { color: #fff; background-color: ${({ bgColor }) => bgColor}; } `;
interface ITextEditor { title: string; contents: string; imageFile?: any[]; setContents: React.Dispatch<React.SetStateAction<string>>; setImageFile?: any; }
const TextEditor = ({ title, contents, imageFile, setContents, setImageFile, }: ITextEditor) => { const { pathname } = useLocation();
const quillRef = useRef(null) as any;
const getBase64Image = (img: any) => { const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx && ctx.drawImage(img, 0, 0, img.width, img.height); const dataUrl = canvas.toDataURL('image'); const imageBase64 = dataUrl.replace(/^data:image\/(png|jpg);base64,/, ''); return { dataUrl, imageBase64 }; }; // 이미지 크기 수정했을 때 const editorFile = () => { const editor = quillRef?.current?.getEditor(); const editorContent = editor.getContents(); // console.log('editorRef => ', editorContent.ops[0]); const { attributes, insert } = editorContent.ops[0];
if (attributes) { const image = new Image(); image.src = insert.image; image.height = attributes.width; image.width = attributes.width; image.alt = 'sample';
const { dataUrl, imageBase64 } = getBase64Image(image); const contentType = 'image';
const blob = base64StringToBlob(imageBase64, contentType); console.log(blob); const file = new File([blob], image.alt, { type: blob.type });
setImageFile((prev: any) => [...prev, file]); }
// console.log(image); };
const onSubmit = (e: FormEvent) => { // 이미지 크기 수정했을 때 editorFile(); };
// 이미지 처음 올렸을때 const saveImage = () => { const input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('accept', 'image/*'); input.click();
input.addEventListener('change', async () => { const file = input.files && input.files[0];
const editor = quillRef.current.getEditor(); const range = editor.getSelection();
if (file) { const reader = new FileReader();
if (file && file.type.match('image.*')) { reader.readAsDataURL(file);
reader.onload = function () { editor.insertEmbed(range.index, 'image', reader.result); editor.setSelection(range.index + 1);
setImageFile((prev: any) => [...prev, file]); }; } } }); };
const modules = useMemo(() => { if (pathname === '/pages/newsPost') { return { toolbar: { container: [ ['bold', 'italic', 'underline', 'strike'], [{ size: ['small', false, 'large', 'huge'] }, { color: [] }], ['image'], ],
handlers: { image: saveImage }, },
imageResize: { parchment: { image: { attributes: ['width', 'height'], }, }, modules: ['Resize', 'DisplaySize'], }, }; } else { // 다른 페이지의 경우 이미지 삽입 기능을 포함하지 않는 설정 반환 return { toolbar: { container: [ ['bold', 'italic', 'underline', 'strike'], [{ size: ['small', false, 'large', 'huge'] }, { color: [] }], ], }, imageResize: { parchment: { image: { attributes: ['width', 'height'], }, }, modules: ['Resize', 'DisplaySize'], }, }; } }, [pathname]);
return ( <Container> <ReactQuill ref={quillRef} modules={modules} theme='snow' value={contents} onChange={setContents} placeholder='여기에 내용을 입력하세요...' /> <Button type='submit' bgColor={'skyblue'} onClick={onSubmit}> 작성하기 </Button> </Container> ); }; export default TextEditor;
2023년 9월 8일 19:44 #97357
codingapple키 마스터원래 이미지 선택하면 바로 서버로 보내서 url만 받아오는데 그 라이브러리는 dataURL로 변환해서 써야하나봅니다 이미지 중복저장이슈는 그 라이브러리 사용법 찾아봐야할듯요
2023년 9월 8일 20:26 #97358
정중식참가자이미지 선택하면 바로 서버로 보내서 url만 받아오는데 라고하셨는뎅..
aws s3에서 프리뷰url이였나? 그걸로 구현은 가능합니다. 근데 유저가 작성안하고 게시글 취소를 한다던가 페이지를 벗어난다던가 인터넷창을 닫는다던가 하면 aws s3에 이미지가 올라가있는데 이건 어떤식으로 처리해줘야할까요? 뭐 게시글 취소 페이지 벗어나기 인터넷창 닫기를 감지해서 aws s3에 방금 올라간 이미지 삭제하기를 구현하면될까요?
2023년 9월 8일 22:48 #97365
codingapple키 마스터넴 페이지 이동이나 컴포넌트 unmount시 서버로 이미지 url 담긴 요청 또 날리면 될듯요 근데 dataURL 방식이 사진용량커지는거말고는 편해보이긴합니다
2023년 9월 9일 17:53 #97434
정중식참가자쌤.. 리액트 클라이언트에서 aws s3 이미지삭제는 불가넝한건가요?
const deleteImageFromS3 = async (fileName: string) => { const s3 = new AWS.S3({ region: REGION, accessKeyId: ACCESS_KEY, secretAccessKey: SECRET_ACCESS_KEY, }); console.log(REGION, ACCESS_KEY, SECRET_ACCESS_KEY); const params = { Bucket: 'plant-newjeans/news', Key: `${fileName}`, };
console.log(s3); console.log(params);
try { await s3.deleteObject(params).promise(); console.log(`Deleted ${fileName} from S3.`); } catch (error) { console.error(`Error deleting ${fileName} from S3: `, error); } };
계속 네트워크에러뜨고 ...흑. .
-
글쓴이글
8 글 보임 - 1 에서 8 까지 (총 8 중에서)
- 답변은 로그인 후 가능합니다.