Braft Editor - Custom Media Upload Function
Introduction
In this article I am going to show you how to implement custom upload and validation function for media upload in Braft Editor.
Braft Editor is a web rich text editor based on draft-js, suitable for React framework, compatible with mainstream modern browsers.
The Problem
I am using Braft Editor for a project and I realised I am facing performance issue in website when I am adding content via Braft Editor. After hours of debugging I found that when images are added in Editor they are converted to PNG and it size also increases.
For example when a 32kb JPG Image was added to got converted to PNG and file size increase to 395 KB.
Code Causing this issue
The code for media upload is in GitHub repository https://github.com/margox/braft-finder
Now one problem with Braft Editor documentation is ,its in Chinese and a non Chinese developer is at the mercy to Google Translate to understand the documentation.
So after not finding any solution in docs, I had to dig into source code for docs. And I found that the problem is caused because of below line of code.
https://github.com/margox/braft-finder/blob/master/src/utils/image.js
export const compressImage = (url, width = 1280, height = 800) => {
return new Promise((resolve, reject) => {
const image = new Image()
image.src = url
image.onerror = function (error) {
reject(error)
}
image.onload = function () {
try {
const compressCanvas = document.createElement('canvas')
const scale = (this.width > width || this.height > height) ? (this.width > this.height ? width / this.width : height / this.height) : 1
compressCanvas.width = this.width * scale
compressCanvas.height = this.height * scale
const canvasContext = compressCanvas.getContext('2d')
canvasContext.drawImage(this, 0, 0, compressCanvas.width, compressCanvas.height)
resolve({
url: compressCanvas.toDataURL('image/png', 1),
width: compressCanvas.width,
height: compressCanvas.height
})
} catch (error) {
reject(error)
}
}
})
}
Solution
As a naive react developer , I had two approaches
- Somehow override Compress Image Function
- Pass a custom upload function as props.
Going through docs , I found there is way to implement custom file upload component using antd .But its not what I wanted
I again had to dig in to , source code , where I found we can pass props to Braft Editor for custom upload and validation.
Code
Now lets dive into some code.
Custom Validation Function
I only wanted user to upload a file less than 100 kb ,So I implemented a custom validation function like below
const validateFn = file => {
let fileSizeError = "File Should be less than 100 kb";
if (file.size > maxFileSize) {
message.warn(fileSizeError);
return false;
}
};
File Upload
In this demo , Custom file upload function converts the image to base64
whithout changing resolution and size. We can also upload this image to server or s3 bucket.
What's important here is once upload is successful in success
call-back function we should return url of the image uploaded
File upload function in this demo
const toBase64 = file =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
const customUpload = props => {
const { file, success, error } = props;
toBase64(file)
.then(res => {
success({ url: res });
})
.catch(err => {
message.warn(" File upload failed");
error(err.message);
});
};
Sample code to upload file to server
const customUpload = props => {
const { file, success, error } = props;
let formData = new FormData();
formData.append("files", file);
fetch('/upload', {
method: 'POST',
body: formData
}).then(res=>{
success({url:res});
}).catch(err=>{
error(err.message);
})
};
Final Code
import React from "react";
import "./styles.css";
import "braft-editor/dist/index.css";
import BraftEditor from "braft-editor";
import { message } from "antd";
const maxFileSize = 100000; //100 kb
export default function App() {
const controls = [
"bold",
"italic",
"underline",
"separator",
"link",
"separator",
"media"
];
const toBase64 = file =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
const customUpload = props => {
const { file, success, error } = props;
toBase64(file)
.then(res => {
success({ url: res });
})
.catch(err => {
message.warn(" File upload failed");
error(err.message);
});
};
const validateFn = file => {
let fileSizeError = "File Should be less than 100 kb";
if (file.size > maxFileSize) {
message.warn(fileSizeError);
return false;
}
};
return (
<div className="App">
<h1>Braft Editor - Custom Media Upload Demo</h1>
<div className="editor-wrapper">
<BraftEditor
language="en"
controls={controls}
media={{ uploadFn: customUpload, validateFn: validateFn }}
contentStyle={{
height: 210,
boxShadow: "inset 0 1px 3px rgba(0,0,0,.1)"
}}
/>
</div>
</div>
);
}
Codesandbox Demo
Conclusion
Thanks for reading! Follow me on Github and Instagram if you want to keep in touch.