1 year ago

#369595

test-img

楊嘉翔

react-quill quill-upload _onUpload to API sometimes notWorking

I use React-Quillquill-upload、Aixos、express
post image to API,but sometimes image address is true ,sometimes is flase MySQL QuillContent

Nice Post Show Nice Post, Bad Post Show Bad Post=>The difference is iamgeColor

Upload image Regardless of success or failure,Server side have been stored image

./CreatePost

    <div style={{ paddingTop: "20px" }}>
        <h3 style={{ paddingBottom: "10px" }}>輸入內容</h3>
        <EditorToolbar />
        <ReactQuill
            theme="snow"
            value={content}
            onChange={setContent}
            modules={modules}
        />
    </div>

./EditorToolbar

import React from "react";
import { Quill } from "react-quill";
import ResizeModule from "@botom/quill-resize-module";
import axios from "axios";
import { ImageHandler, VideoHandler, AttachmentHandler } from "quill-upload";
const config = require('../../config/default.json')

const apiURL = config.apiURL;
//提供Quill套件image、video改變大小用
Quill.register("modules/resize", ResizeModule);
Quill.register("modules/imageHandler", ImageHandler);
Quill.register("modules/videoHandler", VideoHandler);
Quill.register("modules/attachmentHandler", AttachmentHandler);


// Custom Undo button icon component for Quill editor. You can import it directly
// from 'quill/assets/icons/undo.svg' but I found that a number of loaders do not
// handle them correctly
const CustomUndo = () => (
    <svg viewBox="0 0 18 18">
        <polygon className="ql-fill ql-stroke" points="6 10 4 12 2 10 6 10" />
        <path
            className="ql-stroke"
            d="M8.09,13.91A4.6,4.6,0,0,0,9,14,5,5,0,1,0,4,9"
        />
    </svg>
);

// Redo button icon component for Quill editor
const CustomRedo = () => (
    <svg viewBox="0 0 18 18">
        <polygon
            className="ql-fill ql-stroke"
            points="12 10 14 12 16 10 12 10"
        />
        <path
            className="ql-stroke"
            d="M9.91,13.91A4.6,4.6,0,0,1,9,14a5,5,0,1,1,5-5"
        />
    </svg>
);

// Undo and redo functions for Custom Toolbar
function undoChange() {
    this.quill.history.undo();
}
function redoChange() {
    this.quill.history.redo();
}

// Add sizes to whitelist and register them
const Size = Quill.import("formats/size");
Size.whitelist = ["extra-small", "small", "medium", "large"];
Quill.register(Size, true);

// Add fonts to whitelist and register them
const Font = Quill.import("formats/font");
Font.whitelist = [
    "arial",
    "comic-sans",
    "courier-new",
    "georgia",
    "helvetica",
    "lucida",
];
Quill.register(Font, true);

// Modules object for setting up the Quill editor
export const modules = {
    toolbar: {
        container: "#toolbar",
        handlers: {
            undo: undoChange,
            redo: redoChange,
        },
    },
    history: {
        delay: 500,
        maxStack: 100,
        userOnly: true,
    },
    resize: {
        locale: {
            // 圖片、影片調整大小以及定位功能
            altTip: "Hold down the alt key to zoom",
            floatLeft: "Left",
            floatRight: "Right",
            center: "Center",
            restore: "Restore",
        },
    },
    videoHandler: {
        upload: (file) => {
            // return a Promise that resolves in a link to the uploaded image
            return new Promise((resolve) => {
                const fd = new FormData();
                fd.append("video", file);
                _onUpload(fd, resolve,'video');
            });
        },
    },
    imageHandler: {
        upload: (file) => {
            return new Promise((resolve,reject) => {
                const fd = new FormData();
                fd.append("image", file);
                _onUpload(fd, resolve,'image');
            });
        },
    },
};

// Formats objects for setting up the Quill editor
export const formats = [
    "header",
    "font",
    "size",
    "bold",
    "italic",
    "underline",
    "align",
    "strike",
    "script",
    "blockquote",
    "background",
    "list",
    "bullet",
    "indent",
    "link",
    "image",
    "video",
    "color",
    "code-block",
];

// Quill Toolbar component
export const QuillToolbar = () => (
    <div id="toolbar">
        <span className="ql-formats">
            <select className="ql-font" defaultValue="arial">
                <option value="arial">Arial</option>
                <option value="comic-sans">Comic Sans</option>
                <option value="courier-new">Courier New</option>
                <option value="georgia">Georgia</option>
                <option value="helvetica">Helvetica</option>
                <option value="lucida">Lucida</option>
            </select>
            <select className="ql-size" defaultValue="medium">
                <option value="extra-small">Size 1</option>
                <option value="small">Size 2</option>
                <option value="medium">Size 3</option>
                <option value="large">Size 4</option>
            </select>
            <select className="ql-header" defaultValue="3">
                <option value="1">Heading</option>
                <option value="2">Subheading</option>
                <option value="3">Normal</option>
            </select>
        </span>
        <span className="ql-formats">
            <button className="ql-bold" />
            <button className="ql-italic" />
            <button className="ql-underline" />
            <button className="ql-strike" />
        </span>
        <span className="ql-formats">
            <button className="ql-list" value="ordered" />
            <button className="ql-list" value="bullet" />
            <button className="ql-indent" value="-1" />
            <button className="ql-indent" value="+1" />
        </span>
        <span className="ql-formats">
            <button className="ql-script" value="super" />
            <button className="ql-script" value="sub" />
            <button className="ql-blockquote" />
            <button className="ql-direction" />
        </span>
        <span className="ql-formats">
            <select className="ql-align" />
            <select className="ql-color" />
            <select className="ql-background" />
        </span>
        <span className="ql-formats">
            <button className="ql-link" />
            <button className="ql-image" />
            <button className="ql-video" />
        </span>
        <span className="ql-formats">
            <button className="ql-formula" />
            <button className="ql-code-block" />
            <button className="ql-clean" />
        </span>
        <span className="ql-formats">
            <button className="ql-undo">
                <CustomUndo />
            </button>
            <button className="ql-redo">
                <CustomRedo />
            </button>
        </span>
    </div>
);

const _onUpload = async (fd, resolve,type) => {
  axios.defaults.withCredentials = true;
    const result = 
    await axios.post(
        `${apiURL}/api/upload/${type}`,fd
    )
    .catch(err=>console.log(err));
    resolve(`http://localhost:3090/${type}/${result.data.fileName}`);
};

export default QuillToolbar;

Our Back-end developer After update ./NodeJS(expross) Nothing error Message

require('dotenv').config()
const express = require('express')
const app = express()
const cors = require('cors')
const cookieParser = require('cookie-parser')
const fileUpload = require('express-fileupload')

const APIRouter = require('./routes/api')
const { router: authRouter } = require('./routes/auth')

const port = process.env.PORT
app.use(express.json({ limit: '50mb' }))
app.use(express.urlencoded({ extended: true, limit: '50mb' }))
app.use(cors({ credentials: true, origin: process.env.WEB_ORIGIN_URL }))
app.use(cookieParser())
app.use(fileUpload())
app.use(express.static('./public'))

app.use('/periodical/auth', authRouter)
app.use('/periodical/api', APIRouter)

app.listen(port, () => {
    console.log(`Server is running at port ${port}`)
})

Our Back-end developer Before update ./NodeJS(expross) error message enter image description here

require('dotenv').config();
const express = require('express');
const app = express();
const cors = require('cors');
const cookieParser = require('cookie-parser');
const fileUpload = require('express-fileupload');

const APIRouter = require('./routes/api');
const { router: authRouter } = require('./routes/auth');

const port = process.env.PORT;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors({ credentials: true, origin: process.env.WEB_ORIGIN_URL }));
app.use(cookieParser());
app.use(fileUpload());
app.use(express.static('./public'));

app.use('/periodical/auth', authRouter);
app.use('/periodical/api', APIRouter);

app.listen(port, () => {
    console.log(`Server is running at port ${port}`);
});

Nodejs./upload.js


const express = require('express');
const router = express.Router();
const path = require('path');
const util = require('util');

router.route('/video').post(async (req, res) => {
    try {
        const file = req.files.video;
        const extension = path.extname(file.name);
        if (file.size > 100000000) return res.status(400).json({ message: 'File must be less than 100MB' });
        if (file) {
            const fileName = file.md5 + extension;
            const URL = `./public/video/${fileName}`;
            await util.promisify(file.mv)(URL);
            return res.status(200).json({ message: 'Video uploaded successfully', fileName });
        } else {
            return res.status(400).json({ message: 'Lost video file' });
        }
    } catch (error) {
        return res.status(500).json({ error });
    }
});
router.route('/image').post(async (req, res) => {
    try {
        const file = req.files.image;
        const extension = path.extname(file.name);
        if (file.size > 100000000) return res.status(400).json({ message: 'File must be less than 100MB' });
        if (file) {
            const fileName = file.md5 + extension;
            const URL = `./public/image/${fileName}`;
            await util.promisify(file.mv)(URL);
            return res.status(200).json({ message: 'Image uploaded successfully', fileName });
        } else {
            return res.status(400).json({ message: 'Lost image file' });
        }
    } catch (error) {
        return res.status(500).json({ error });
    }
});

module.exports = router;

node.js

reactjs

express

axios

react-quill

0 Answers

Your Answer

Accepted video resources