在Quill JS中使用base64内联图片时,如何保留图片的文件名?

前端开发 2026-07-09

我正在使用Quill JS(React)来撰写邮件。上传图片时,Quill会把它转换为一个base64字符串,放在 <img src='base64datas....'> 标签内。然而,我在后端(Python)需要原始文件名以便正确设置附件名称。目前我只能得到base64数据,文件名已经丢失。

有没有办法拦截图片上传,将文件名作为一个数据属性存储(比如 data-filename),或有其他办法把文件名和HTML正文一起发送?

代码:

 useEffect(() => {
        if (editorRef.current && !quillInstance.current) {

            quillInstance.current = new Quill(editorRef.current, {
                placeholder: 'Type your message here...',
                theme: 'snow',
                modules: {
                    toolbar: [
                        [{ 'header': [1, 2, false] }],
                        ['bold', 'italic', 'underline', 'strike', 'blockquote'],
                        [{ 'list': 'ordered' }, { 'list': 'bullet' }],
                        [{ 'align': [] }],
                        ['link', 'image'],
                        ['clean'],
                        ["table-better"],


                    ],
                    table: false,
                    "table-better": {
                        language: "en_US",
                        bounds:document.body,
                        menus: [
                            "column",
                            "row",
                            "merge",
                            "table",
                            "cell",
                            "wrap",
                            "copy",
                            "delete",
                        ],
                        toolbarTable: true,
                    },
                    imageResizer: {
                        modules: ['Resize', 'DisplaySize', 'Toolbar'],

                    },

                    toggleFullscreen: {
                        buttonTitle: 'Toggle fullscreen',

                    },

                }
            });
        }
    }, []);

解决方案

由于Quill将图片转换为base64,默认情况下文件名会丢失。要解决这个问题,你需要:

  1. 扩展Image Blot(图片Blot),以允许自定义属性(例如 data-filename)。
  2. 覆盖Uploader模块,从 File 对象中获取文件名并将其注入到标签中。

  3. 在前端扩展Image Blot(前端):

useEffect(() => {
        if (editorRef.current && !quillInstance.current) {

            const quill = new Quill(editorRef.current, {
                placeholder: 'Type your message here...',
                theme: 'snow',
                modules: {
                    toolbar: [
                        [{ 'font': [] }],
                        ['bold', 'italic', 'underline', 'strike', 'blockquote'],
                        [{ 'list': 'ordered' }, { 'list': 'bullet' },{ 'list': 'check' }],
                        [{ 'script': 'sub'}, { 'script': 'super' }],     
                        [{ 'indent': '-1'}, { 'indent': '+1' }],         
                        [{ 'align': [] }],
                        ['link', 'image','formula'],
                        ['clean'],
                        ["table-better"],
                        [{ 'color': [] }, { 'background': [] }],
                    ],
                    table: false,
                    "table-better": {
                        language: "en_US",
                        bounds: document.body,
                        menus: ["column", "row", "merge", "table", "cell", "wrap", "copy", "delete"],
                        toolbarTable: true,
                    },
                    imageResizer: {
                        modules: ['Resize', 'DisplaySize', 'Toolbar'],
                    },
                    toggleFullscreen: {
                        buttonTitle: 'Toggle fullscreen',
                    },
                }
            });

            //get uploaded image name and set to img tag attribute and also print in console

            quillInstance.current = quill;


            const uploader = quill.getModule('uploader');
            if (uploader) {
                uploader.options.handler = (range, files) => {
                    const promises = files.map((file) => {
                        return new Promise((resolve) => {
                            const reader = new FileReader();
                            reader.onload = (e) => {
                                resolve({ data: e.target.result, name: file.name });
                            };
                            reader.readAsDataURL(file);
                        });
                    });

                    Promise.all(promises).then((images) => {
                        images.forEach((img, index) => {
                            const currentIndex = range.index + index;


                            quill.insertEmbed(currentIndex, 'image', img.data, 'user');


                            setTimeout(() => {
                                const imgTags = quill.root.querySelectorAll(`img[src="${img.data}"]`);
                                const targetImg = imgTags[imgTags.length - 1];
                                if (targetImg) {
                                    targetImg.setAttribute('data-filename', img.name);

                                    //this will print the filename in console when you upload the image and also set a attribute to the img tag which we can use later to get the filename when sending mail to backend
                                    console.log("Filename set:", img.name);
                                }
                            }, 100);
                        });
                    });
                };
            }
        }
    }, []);
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章