How to upload an image in mongoose-node app using ckeditor. File will be uploaded to s3 - node.js

I'm using CKEditor to upload content in mongoose.
I want images to be uploaded along with the content.
I'm storing the images to s3 and mongodb stores the image path in string (when not uploading with ckeditor).
I'm trying to use this module
https://github.com/mjadobson/ckeditor5-sss-upload
I'm trying this code
build-config.js
module.exports = {
// ...
plugins: [
"#ckeditor/ckeditor5-essentials/src/essentials",
// ...
//'#ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter',
//'#ckeditor/ckeditor5-easy-image/src/easyimage',
"ckeditor5-sss-upload/src/s3upload"
// ...
],
// ...
config: {
toolbar: {
items: [
"headings",
"bold",
"italic",
"imageUpload",
"link",
"bulletedList",
"numberedList",
"blockQuote",
"undo",
"redo"
]
}
// ...
}
};
seminar.js
const build_config=require('../build-config');
router.get('/add',ensureAuthenticated,(req,res)=>{
SeminarGamenameConf.find().then(gameName_list=>{
SeminarGametypeConf.find().then(gameType_list=>{
console.log(gameType_list);
res.render('cms/seminar/add',{
gameName_list_array:gameName_list,
gameType_list_array:gameType_list,
country: countries,
build_config:build_config
});
})
})
});
//add.handlebars
<script src="/ckeditor5-build-classic/ckeditor.js"></script>
<form action="/cms/seminar/add" enctype="multipart/form-data" method="post" >
<div class="form-group">
<label for="seminar_detail">Seminar Details</label>
<textarea class="form-control" id="editor1" name="seminar_detail</textarea>
<input type="submit" value="submit"/>
</div>
</form>
<script>
ClassicEditor.create(document.querySelector("#editor"), {
s3Upload: {
policyUrl: "http://127.0.0.1/my-upload-endpoint",
mapUrl: ({ location, bucket, key }) => {
return location;
}
}
});
</script>
I'm really confused. I don't know how to upload images to s3 using ckeditor (in between the details).
Please help.
If there is any other method, please reply

Related

Raw Binary Data for Microsoft Cognitive Service API

For the Microsoft Azure Cognitive Services API, the image needs to be passed in this format
Input passed within the POST body. Supported input methods: raw image binary.
So, I was very lost on how to convert the image the user is uploading into that format and make an API request. I'm using ReactJS on the front-end with a NodeJs backend. Could someone please help me get the image in the correct format? I'm not sure whether I have to read it in as an Array Buffer?
import React, { Component } from 'react';
import Button from 'react-bootstrap/Button';
class Dashboard extends Component {
constructor(props) {
super(props);
this.state ={
file: null
}
}
onSubmit = () => {
console.log(this.state.file);
// console.log(window.atob(this.state.file));
}
onChange = (e) => {
const file = e.target.files[0];
const reader = new FileReader()
reader.addEventListener("load", () => {
// convert image file to base64 string
console.log(reader);
// if (reader.result.includes("data:image/png;base64,")) {
// img = reader.result.replace("data:image/png;base64,", "");
// } else {
// img = reader.result.replace("data:image/jpeg;base64,", "");
// }
//this.setState({file: img});
}, false);
if (file) {
reader.readAsArrayBuffer(file);
}
}
render() {
return(
<div>
<h3 style={{padding: '20px', textAlign: 'center', color: 'white', fontWeight: '100'}}>
Customize your playlist based on your mood!
</h3>
<h5 style={{margin: '30px', padding: '0px',textAlign: 'center', color: 'grey', display:'block'}}>
Click a picture of your surroundings or simply upload one based on what you're currently in the mood for and
<br />
<br />
TuneIn will add a playlist according to your liking!
</h5>
<form onSubmit={this.onSubmit}>
<h1>File Upload</h1>
<input type="file" accept="image/png, image/jpeg" onChange={this.onChange}/>
<button type="submit">Upload</button>
</form>
</div>
);
}
}
export default Dashboard;
Here is the sample for Analyzing a local image using the Computer Vision REST API and javascript.
https://github.com/Azure-Samples/cognitive-services-quickstart-code/blob/master/javascript/ComputerVision/ComputerVisionQuickstart.js

Upload multiple Files in angular node multer

I am facing problem while uploading multiple files in angular, node, multer.
Last file in array is uploaded to server.
Here is my HTML.
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="Anti Black List" id="4" #fileDataAntiBlackList (onFileSelected)="onFileSelected($event ,fileDataAntiBlackList)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="Shop Act" id="3" #fileDataShopAct (onFileSelected)="onFileSelected($event ,fileDataShopAct)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="Professional Tax" id="2" #fileDataPRO (onFileSelected)="onFileSelected($event ,fileDataPRO)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="GST Copy" id="1" #fileDataGST (onFileSelected)="onFileSelected($event ,fileDataGST)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<mat-label>First name</mat-label>
<input formControlName="f_name" matInput type="text" name="first_name" placeholder="First name" required/>
<mat-label>Last name</mat-label>
<input formControlName="l_name" matInput type="text" name="Last_name" placeholder="Last name" required/>
<button mat-raised-button color="primary" class="mx-4" (click)="onSubmit()"
[disabled]="uploader.getNotUploadedItems().length && signupForm.invalid">Upload And Save </button>
There are more fields, but i have shown less here.
Following is TS file code
filesToUpload: Array<File> = [];
fileChangeEvent(fileInput: any) {
this.filesToUpload = <Array<File>>fileInput.target.files;
//this.product.photo = fileInput.target.files[0]['name'];
}
onSubmit() {
//let files = this.getFiles();
let dbId: number;
let formData = new FormData();
const files: Array<File> = this.filesToUpload;
for(let i = 0; i < files.length;i++){
formData.append("files", files[i], files[i]['name']);
}
formData.append('first_name',this.signupForm.value.f_name);
this.http.post('http://localhost:3000/api/newUpload', formData)
.map(files => files)
.subscribe(files => console.log('files', files));
return false;
}
This is my backend API
Upload
let user_storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, DIR);
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + '' + path.extname(file.originalname));
}
});
let upload = multer({ storage: user_storage }).array('files',10);
API function
router.post('/newUpload',function(req,res){
console.log('before upload',req.body);
upload(req,res,function(err) {
//console.log(req.body);
//console.log(req.files);
if(err) {
return res.end("Error uploading file.");
}
console.log('files', req.files);
console.log(req.body);
res.send(req.files);
//res.end("File is uploaded");
});
});
This is what i have tried. Only last file in array is save in uploads folder.
Also i want to insert first name , last name etc to database but when i console req.body is gives empty json {}
Edit quetion
i got where i am missing.
Its in angular code : when i print
const files: Array<File> = this.filesToUpload;
i get last file which i uploaded. means it takes last file which is uploaded not all files.
so i use following function
getFiles(){
return this.uploader.queue.map((fileItem) => {
return fileItem.file;
});
}
So in onsubmit function
onSubmit() {
let files = this.getFiles();
let formData = new FormData();
for(let i = 0; i < files.length;i++){
console.log(files[i]);
formData.append("files", files[i],files[i]['name']);
}
When i console files[i], get all files.
But in line formData.append line i get following error
Argument of type 'FileLikeObject' is not assignable to parameter of type 'string | Blob'.
Property 'slice' is missing in type 'FileLikeObject' but required in type 'Blob
P.S : when i send file name in formdata.append, i get all file names in node serevr.
After trying different solutions, finally i got working solutions by which multiple files and other input fields are also send to sever.
In my Edit part of question, i have use following function
getFiles(){
return this.uploader.queue.map((fileItem) => {
return fileItem.file;
});
}
above code was giving error. I have just changed return line.
from
return fileItem.file;
to
return fileItem.file.rawFile;
Thats it. All remaining code is same as in edit.
you forget to add multer middleware to your router.post
it should be
outer.post('/newUpload',
upload.array('myFiles', 12),
function(req,res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
res.send(req.files);
//res.end("File is uploaded");
});
});

How to upload multiple images to Sails.js application

Backstory
I'm building an online marketplace for used cars where owners can list their cars for sale and buyers can find affordable used cars more easily.
I'm using Sails.js v1.0 as my app's Node.js framework.
Challenge
I want users to be able to add images to each car they've listed, Craigslist-style.
Current Implementation
Here's what I have thus far...
In images.ejs view file I have an ajax-form element:
<ajax-form class="" action="images" :syncing.sync="syncing" :cloud-error.sync="cloudError" #submitted="submittedForm()" :handle-parsing="handleParsingForm" enctype="multipart/form-data">
<div class="form-outer flex justify-center items-center h-100 bt bw2">
<div class="form-inner bg-yellow pa3 w-100">
<div class="mb3 w-100">
<label class="db tl mv2 f4" for="upload">Upload</label>
<input class="pv3" id="upload" type="file" :class="[formErrors.upload ? 'is-invalid' : '']" v-on:change>
<div class="bg-light-red light-gray pa2 br2 mt1" v-if="formErrors.upload">Please select at least one image.</div>
</div>
<p class="bg-light-red light-gray pa2 br2 mt1" v-if="cloudError"><small>An error occured while processing your request. Please check your information and try again, or contact support if the error persists.</small></p>
<div class="">
<ajax-button :syncing="syncing" class="bg-green pa2 ba b--dark-gray br2 bw1 b circular-bold">Add images.</ajax-button>
</div>
</div>
</div>
</ajax-form>
This form submits to the controller at POST: cars/images.js:
module.exports = {
friendlyName: 'Images',
description: 'Allow users to upload images of car.',
inputs: {
},
exits: {
},
fn: async function (req, res) {
req.file('upload').upload({
// don't allow the total upload size to exceed ~10MB
maxBytes: 10000000
},function whenDone(err, uploadedFiles) {
if (err) {
return res.serverError(err);
}
// If no files were uploaded, respond with an error.
if (uploadedFiles.length === 0){
return res.badRequest('No file was uploaded');
}
// Get the base URL for our deployed application from our custom config
// (e.g. this might be "http://foobar.example.com:1339" or "https://example.com")
var baseUrl = sails.config.custom.baseUrl;
// Save the "fd" and the url where the upload for a user can be accessed
User.update(req.session.userId, {
// Generate a unique URL where the upload can be downloaded.
uploadUrl: require('util').format('%s/user/upload/%s', baseUrl, req.session.userId),
// Grab the first file and use it's `fd` (file descriptor)
uploadFd: uploadedFiles[0].fd
})
.exec(function (err){
if (err) return res.serverError(err);
return res.ok();
});
});
}
};
This controller/sails action is using the standard req/res objects within the Sails.js actions2 format.
All of the Sails documentation on file uploads points to the Sails body-parser implementation called Skipper, but I feel the documentation is lacking on the new actions2 syntax.
Can anyone point me to a concrete example of implementing this file upload feature, especially for uploading multiple image files?

Upload image to database using angular

I got stuck while uploading updating user avatar on my website. I'm using angular and need to upload image using form and get base64 encoding of this image to pass as a parameter into my backend.
onUploadFinished(event){
const avatar ={
avatar:event.file
}
console.log(avatar)
//validate avatar
if(!this.validateService.validateAvatarUpdate(avatar.avatar)){
this.flashMessage.show('Please, select a new avatar', {cssClass: 'alert-danger', timeout:3000});
return false;
}
this.updateService.updateAvatar(avatar).subscribe(data=>{
console.log()
if(data/*.success*/){ //commented cause response doesnt have property success but still registering user without displaying the flash message
this.flashMessage.show('You successfuly changed your avatar', {cssClass: 'alert-success', timeout:3000});
this.router.navigate(['/profile'])
this.authService.getProfile().subscribe(profile=>{
this.user = profile.user;
},
err=>{
console.log(err);
return false;
});
}else{
this.flashMessage.show('Something went wrong', {cssClass: 'alert-danger', timeout:3000});
this.router.navigate(['/profile'])
}
});
}
I was trying to use ng2-image-upload here is html
<h6>Upload new photo...</h6>
<!-- <form (submit)="onUserAvatarSubmit()" enctype="multipart/form-data">
<input type="file" name="avatar" class="text-center center-block well well-sm">
<p></p>
<input class="btn btn-primary" value="Upload" type="submit">
</form> -->
<image-upload name="avatar" [class]="'customClass'"
[headers]="{Authorization: this.authToken}"
[buttonCaption]="'Choose an Image'"
[dropBoxMessage]="'or just drop them here'"
(uploadFinished)="onUploadFinished($event)"
[url]="''">
</image-upload>
Maybe anyone had such experience with uploading images, so give me some tips how to deal with it. Thanks here is a screenshot So you see when displaying this image we can see its base64 but I cant take it.

Vue js 2 Method not working from click event

I have a vue component which prints out a list of radio buttons. I have a watch on internalValue which sends the selected value to the root
I am trying to send a console.log on a click event using a method called doSomething but it is not working. Furthermore I am not getting any errors or warnings.
Load Component
Vue.component('topic', require('./components/Topicselect.vue'));
Use Component
<div class="form-group" id="topic">
<topic v-model="selectedTopic"></topic>
</div>
Initialise Vue
new Vue({
el: '#topic',
data: {
selectedTopic: null
}
});
Component
<template>
<div>
<label v-for="topic in topics" class="radio-inline radio-thumbnail" style="background-image: url('http://s3.hubsrv.com/trendsideas.com/profiles/74046767539/photo/3941785781469144249_690x460.jpg')">
<input type="radio" v-model="internalValue" :click="doSomething" name="topics_radio" :id="topic.id" :value="topic.name">
<span class="white-color lg-text font-regular text-center text-capitalize">{{ topic.name }}</span>
</label>
</div>
</template>
<script>
export default {
props: ['value'],
data () {
return {
internalValue: this.value,
topics: []
}
},
mounted(){
axios.get('/vuetopics').then(response => this.topics = response.data);
},
watch: {
internalValue(v){
this.$emit('input', v);
console.log('the value is ' + this.value);
}
},
methods: {
doSomething: function (){
console.log('doSomething is firing');
}
}
}
</script>

Resources