custom url in image upload jodit editor - javascript

I have implemented Jodit Editor (react)https://github.com/jodit/jodit-react, Insert Image option, in which can you upload the image, which saves to the default option by the Editor,
I would like to know how to use custom url and insert the image in editor
Jodit default behaviour
config:{
readonly: false,
enableDragAndDropFileToEditor: true,
uploader: { url: "https://xdsoft.net/jodit/connector/index.php?action=fileUpload"}
}
Expected
How to do adding custom url
config:{
readonly: false,
enableDragAndDropFileToEditor: true,
uploader: { url: "www.xyz.com/upload"}
}

In this repository, https://github.com/GilianMoa/jodit-editor-react
I'm uploading images with Cloudinary api.
Hope I can help you with this code.
I create a custom buttom:
uploadImageButton = () => {
Jodit.defaultOptions.controls.uploadImage = {
name: 'Upload image to Cloudinary',
iconURL: "https://www.kindpng.com/picc/m/261-2619141_cage-clipart-victorian-cloud-upload-icon-svg-hd.png",
exec: (async (editor) => {
await this.imageUpload(editor);
})
};
}
Then I create a method to open a dialog to pick the image and send to a service which send a post with the image file formData to cloudinary.
//dialog method
imageUpload = (editor) => {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.click();
input.onchange = async function () {
const imageFile = input.files[0];
if (!imageFile) {
return;
}
if (!imageFile.name.match(/\.(jpg|jpeg|png)$/)) {
return;
}
const imageInfo = await FileUpload(imageFile);;
this.insertImage(editor, imageInfo.url);
}.bind(this);
}
//this method insert the image inside the editor after the upload is done.
insertImage = (editor, url) => {
const image = editor.selection.j.createInside.element('img');
image.setAttribute('src', url);
editor.selection.insertNode(image);
}
// this method send the image to cloudinary
export const FileUpload = async (file) => {
let result = null;
let formData = new FormData();
formData.append('file', file);
formData.append('upload_preset', `${process.env.REACT_APP_CLOUDINARY_UPLOAD_PRESET}`);
await fetch(`https://api.cloudinary.com/v1_1/${process.env.REACT_APP_CLOUDINARY_CLOUD_NAME}/image/upload`, {
method: 'POST',
body: formData
})
.then((response) => response.json())
.then((data) => {
result = data;
})
.catch((error) => {
console.error('Error:', error);
});
return result;
}

I use jodit-react and upload img success ! the code is here hope to help you.
<JoditEditor
ref={this.editor}
value={'this.state.content'}
config={{
language: 'zh_cn',
toolbarButtonSize: 'large',
uploader: {
url: '/manage/upload', //your upload api url
insertImageAsBase64URI: false, not inster base64
imagesExtensions: ['jpg', 'png', 'jpeg', 'gif'],
//headers: {"token":`${db.token}`},
filesVariableName: function (t) {
return 'files[' + t + ']';
}, //"files",
withCredentials: false,
pathVariableName: 'path',
format: 'json',
method: 'POST',
prepareData: function (formdata) {
return formdata;
},
isSuccess: function (e) {
debugger;
return e.success;
},
getMessage: function (e) {
return void 0 !== e.data.messages && Array.isArray(e.data.messages)
? e.data.messages.join('')
: '';
},
process: function (resp: any) { //success callback transfrom data to defaultHandlerSuccess use.it's up to you.
let files = [];
files.unshift(resp.data);
return {
files: resp.data,
error: resp.msg,
msg: resp.msg,
};
},
error: function (this: any, e: Error) {
this.j.e.fire('errorMessage', e.message, 'error', 4000);
},
defaultHandlerSuccess: function (this: Uploader, resp: IUploaderData) { // `this` is the editor.
const j = this;
debugger;
if (resp.files && resp.files.length) {
const tagName = 'img';
resp.files.forEach((filename: string, index: number) => { //edetor insertimg function
const elm = j.createInside.element(tagName);
elm.setAttribute('src', filename);
j.s.insertImage(elm as HTMLImageElement, null, j.o.imageDefaultWidth);
});
}
},
defaultHandlerError: function (this: any, e) {
this.j.e.fire('errorMessage', e.message);
},
contentType: function (e) {
return (
(void 0 === this.jodit.ownerWindow.FormData || 'string' == typeof e) &&
'application/x-www-form-urlencoded; charset=UTF-8'
);
},
},
}}
/>
I have test ok.

Related

Occasionally uploading larger files

On moving to the next step in the form I have run some checks. One is to stop photos over 10mb and preventing .heic files from being upload. 90% of the time it works, but now and again files are let through.
Any help with a better written solution or a reason why this may fail and let large files or .heic file through.
var upload_one = document.getElementById("image_one");
if(upload_one.files.length > 0) {
if (upload_one.files.item(0).size >= '10485760') {
upload_one.className += " invalid";
valid = false;
alert("Photo is too large. Photos need to be under 10mb")
}
fileName = document.querySelector('#image_one').value;
extension = fileName.split('.').pop();
if (extension == 'heic') {
upload_one.className += " invalid";
valid = false;
alert("Files can only be .png, .jpg or .jpeg")
}
}
You should have a look at presigned Url using S3 bucket on aws.
Basically you generate an upload url where you can upload big files direclty to S3.
Personally I use a lambda to generate this presignedUrl and I return it to front end then.
Backend
const AWS = require("aws-sdk");
const S3 = new AWS.S3();
const { v4: uuidv4 } = require("uuid");
const getUrl = async (params) => {
return await new Promise((resolve, reject) => {
S3.getSignedUrl("putObject", params, (err, url) => {
if (err) {
reject(err);
} else {
resolve({
statusCode: 200,
url,
});
}
});
});
};
exports.handler = async (event, context) => {
const id = uuidv4();
const { userId } = event?.queryStringParameters;
const params = {
Bucket: process.env.INVOICE_BUCKET,
Key: `${userId}/${id}.csv`,
ContentType: `text/csv`,
ACL: "public-read",
};
try {
const { url } = await getUrl(params);
return handleRes({ message: `Successfully generated url`, url, key: `${id}.csv`, publicUrl: `https://yourBucket.s3.eu-west-1.amazonaws.com/${userId}/${id}.csv` }, 200);
} catch (e) {
console.error(e);
return handleRes({ message: "failed" }, 400);
}
};
Front end
$(function () {
$("#theForm").on("submit", sendFile);
});
function sendFile(e) {
e.preventDefault();
var urlPresigned;
var publicUrl;
var key;
$.ajax({
type: "GET",
url: `https://yourId.execute-api.eu-west-1.amazonaws.com/Prod/file-upload-to-bucket?userId=${userId}`,
success: function (resp) {
urlPresigned = resp.url;
publicUrl = resp.publicUrl;
key = resp.key;
var theFormFile = $("#theFile").get()[0].files[0];
$.ajax({
type: "PUT",
url: urlPresigned,
contentType: "text/csv", // Put meme type
processData: false,
// the actual file is sent raw
data: theFormFile,
success: function () {
// File uploaed
},
error: function (err) {
console.log(err);
},
});
},
});
}

Quill undefined when uploading a file from local machine

I am a beginner working with React.js and Quill.
I am trying to upload a file from my local machine by rewriting existing imageHandler. It does take the file, but do not upload it. The error is following: TypeError: Cannot read property 'quill' of undefined. Here is my code so far:
function imageHandler() {
console.log('Image Handler called');
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.click();
input.onchange = async function () {
const file = input.files[0];
console.log('User trying to upload this:', file);
const formData = new FormData()
if (file !== null) {
formData.append('file', file)
}
fetch('https://smartquestionapi.advancity.net/Image', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData
}).then(function (response) {
if (response.ok) {
return response.json()
} else {
return { "error": true }
}
}).then(function (json) {
console.log(file.name);
var cursorPosition = this.quill.getSelection();
var imagePath = "https://smartquestionapi.advancity.net/Images/" + file.name;
this.quill.insertEmbed(cursorPosition.index, 'image', imagePath, Quill.sources.USER);
return json;
}).catch(err => {
console.log("eror: ", err);
})
}.bind(this);
}
The code crushes exactly in then(function (json){ function.
I think is because you are not binding this in this part:
.then(function (json) {
console.log(file.name);
var cursorPosition = this.quill.getSelection();
You can solve it with an arrow function:
.then((json) => {
console.log(file.name);
var cursorPosition = this.quill.getSelection();
Take also a look here, to see the differences between function(){} and (args..) => {}

Download an image using axios post request

I need base64 image chart from 'http://export.highcharts.com/'
getImg () {
const self = this;
axios.post('http://export.highcharts.com/', { options: self.$refs['lineChart'].options, type: 'image/png' }).then(function (response) {
base64.encode(response.data)
}).catch(function (e) {
console.log(e)
});
},
Here you can get image and convert it to base64. also similar to this question you can check the following link to get more information.
function getBase64(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => Buffer.from(response.data, 'binary').toString('base64'))
}
This works fine
getImg () {
const self = this;
axios.post('http://export.highcharts.com/', { options: self.$refs['lineChart'].options, type: 'image/png' }, { responseType: 'arraybuffer' }).then(function (response) {
let PNGBase64 = 'data:image/png;base64,' + Buffer.from(response.data, 'binary').toString('base64')
}).catch(function (e) {
console.log(e)
});
},

Redux Thunk - Change state before REST request

I am quite new to Redux Thunk and have an issue that I want to update a contract with a 'FileList' (file appendix), but if I use JSON.stringify the file will have a 0 value. If I convert the file to Base64 this problem is solved, but the PUT request is performed before the file is converted.
I searched a lot about Redux Thunk and think it might be some issue with Dispatch, I tried quite a lot and didn't become much wiser. Most of the things that I tried returned: "Actions must be plain objects. Use custom middleware for async actions."
Would appreciate some help or some search suggestions..
ps. contract.answers[0].answer[0] is the file. This acquires some refactoring, but first it needs to work.
const toBase64 = (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
export function updateContract(contract) {
const base64File = toBase64(contract.answers[0].answer[0]);
base64File.then((value) => {
contract.answers[0].answer[0] = value; //Set file as base64
});
return {
type: SAVE,
fetchConfig: {
uri: contract._links.self,
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(contract), // Does not handle files
failureHandler(error) {
const {
details,
status,
} = error;
// If the contract was invalid, throw form errors:
if (status.code === 400 && details) {
// Map the question ids to fields:
throw new SubmissionError(Object.keys(details).reduce(
(acc, questionId) => {
acc[`question${questionId}`] = details[questionId];
return acc;
},
{},
));
}
return {
type: SAVE_FAILURE,
error,
};
},
successHandler(json) {
return {
type: SAVE_SUCCESS,
data: json,
};
},
},
};
}
Kind regards,
Gust de Backer
This happen because toBase64 return a Promise and itself is async, so in your case is necessary encapsule inside a new then.
export function updateContract(contract) {
const base64File = toBase64(contract.answers[0].answer[0]);
base64File.then((value) => {
contract.answers[0].answer[0] = value; //Set file as base64
});
return (dispatch) => {
base64File.then(() => dispatch({
type: SAVE,
fetchConfig: {
uri: contract._links.self,
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(contract), // Does not handle files
failureHandler(error) {
const {
details,
status,
} = error;
// If the contract was invalid, throw form errors:
if (status.code === 400 && details) {
// Map the question ids to fields:
throw new SubmissionError(Object.keys(details).reduce(
(acc, questionId) => {
acc[`question${questionId}`] = details[questionId];
return acc;
}, {},
));
}
return {
type: SAVE_FAILURE,
error,
};
},
successHandler(json) {
return {
type: SAVE_SUCCESS,
data: json,
};
},
},
}))
};
}
Yes, the redux accept a function as return, that function receive a dispatch on params, you can use it to dispatch the request after convert is ready :)

Is it possible to send data and files in the same request?

I have an API that receives uploads of APP files and images
To send from APP to the API I use fetch
const data = new FormData();
let i = 0;
export const dataPush = (fileUri, fileType, fileName) => {
data.append('file'+i, {
uri: fileUri,
type: fileType,
name: fileName
});
i++;
};
export const uploadFiles = () => {
console.log(data);
fetch('http://192.168.0.23/apiapp/public/api/annex', {
method: 'post',
body: data
}).then(res => {
console.log(res)
});
}
But I'd like to send in the same request data obtained from a form
But I did not find a way to do it, always or just send the data, or just send the files
Is it possible to send everything in the same request? And if possible, how?
You just append whatever data that you desire that isn't file data to the FormData object.
data.append("not_a_file", "This is a string");
I did so based on Quentin's response and it worked
const formData = new FormData();
const i = 0;
export const filePush = (fileUri, fileType, fileName) => {
formData.append('file'+i, {
uri: fileUri,
type: fileType,
name: fileName
});
i++;
};
export const dataPush = (name, content) => {
formData.append(name, content);
};
export const uploadFiles = () => {
fetch('http://192.168.0.23/apiapp/public/api/annex', {
method: 'post',
body: formData
}).then(res => {
console.log(res._bodyText)
}).catch(error => {
console.log(error.message)
});
}

Categories

Resources