Image is not validating: "The avatar must be an image" - laravel

I'm using a modal to preview an avatar. The even that triggers the modal is outside the ability to have a parent child structure so I have to pass the file object to my UpdateAvatar component.
Html
<avatar-update :image-blob="avatarFile" :show="avatarModalShow"
#close="avatarModalShow = !avatarModalShow"
:change-avatar="updateCrop"> </avatar-update>
Root Instance
data() {
return {
avatarModalShow: false,
avatarFile: null,
}
},
methods: {
onFileChange: function(e) {
this.avatarFile = e.target.files[0];
this.avatarModalShow = !this.avatarModalShow;
},
},
AvatarUpdate
export default {
props: ['show','imgUrl','changeAvatar','imageBlob'],
data() {
return {
image: null,
message: null,
internalImageObj: null
}
},
watch: {
changeAvatar: function(){
this.image = this.imgUrl;
},
imageBlob: function (newVal) {
let reader = new FileReader()
reader.readAsDataURL(newVal)
reader.addEventListener('load', () => {
this.internalImageObj = reader.result
}, false)
}
},
updated: function () {
this.image = this.imgUrl;
},
methods: {
close: function(){
this.$emit('close');
},
submitAvatar: function(){
const avatarFormData = new FormData();
avatarFormData.append('avatar', this.internalImageObj);
console.log(avatarFormData);
axios({
method: 'POST',
url: '/profile/avatar',
data: avatarFormData,
}).then(function (response) {
this.message = "Your avatar has been submitted";
}.bind(this))
.catch(function (error) {
console.log(error);
});
}
}
}
UserController
public function avatar(Request $request)
{
$request->validate([
'avatar' => 'image',
]);
return $request->all();
}
When I return $request->all(); in the avatar function with no validation on the UserController I'm getting this output: avatar:"data:image/png;base64,iVBORw0KGgoAAAANSUhSomeLongString
Error
{message: "The given data was invalid.", errors: {avatar: ["The avatar must be an image."]}}
errors
:
{avatar: ["The avatar must be an image."]}
avatar
:
["The avatar must be an image."]
0
:
"The avatar must be an image."
message
:
"The given data was invalid."

this is because your validation rule for avatar is image or mimes:jpeg,bmp,png this it will look for a file where the mime type is jpeg,bmp,png. but in your case your axios send it as a base64 which don't have a mime type. you need to include 'Content-Type': 'multipart/form-data' header in your axios object like this,
axios({
method: 'POST',
url: '/profile/avatar',
data: avatarFormData,
headers: {
'Content-Type': 'multipart/form-data'
}
})
hope this helps.

Related

Upload input image file to database with BLOB datatype Vuejs

We have a form that must save image file to our database with blob datatype
what i currently did is convert the file to dataURL and dataURL to BLOB
selectFile(){
var reader = new FileReader()
reader.readAsDataURL(this.$refs.file.files[0])
reader.onload = () => {
var dataURL = reader.result;
console.log(dataURL);
var arr = dataURL.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
var file = new Blob([u8arr], {type:mime});
console.log(test);
this.file = file
}
},
and from the console it was successful i was able to convert IMG to dataURL to Blob, the problem is when submitting the form, so i have a axios
async OnSubmit() {
this.loading = true;
const formData = new FormData();
formData.append('first_name', this.first_name);
formData.append('signature_1_1', this.file);
const config = {
headers: {
'Content-Type': 'multipart/form-data',
}
};
try{
let{data, status, response} = await
axios.post('/api/auth/register', formData ,
config);
this.loading = false;
if ([201, 200].indexOf(status) > -1) {
Swal.fire({
title: "Success!",
text: `Successfully Register RE Developer!`,
icon: "success",
allowOutsideClick: false,
showCancelButton: false,
confirmButtonText: "Close",
}).then((result) => {
this.$router.push({ name: "login" });
});
}
catch (error) {
// this.errors = `${error.errors}`;
this.loading = false;
Swal.fire({
title: "Oops!",
text: `Something went wrong!`,
icon: "error",
allowOutsideClick: false,
showCancelButton: false,
confirmButtonText: "Close",
});
}
based on the headers the blob is there
but Im still getting error "Error Code : 1465\r\nError Message : ORA-01465: invalid hex number
and i also tried the direct approach which is "formData.append('signature_1_1', this.$ref.file.files[0]);" but same error
Register Controller
function register(Request, $request){
$validated_data= TableValidate::validateTable($request);
$data= Table::create($validated_data);
}
For Validation
public static function validateTable(Request $request) {
$request->validate([
'first_name' => 'required|string',
)];
$data = [
'first_name' => $request->first_name,
'signature_1_1' => $request->signature_1_1,
]
}
I hope someone can help me with this

FormData upload on Expo

Using expo, whenever I run a post request with a FormData object with an appended JSON and a image file, I get
"error": "Unsupported Media Type",
"message": "Content type 'application/octet-stream' not supported",
"path": "/visitas/",
"status": 415,
[…]
as a response from the backend (which runs Spring Boot), but whenever I replicate the request into a HTTP Client (Insomnia on this case) the request follow as it should, and I can retrieve and see the image back as I should.
Code
Visitas.js
[…]
async function startVisita(checkin) {
// Checkin contains file uri and some other things
try {
const location = await getLocation();
const formData = new FormData();
formData.append('object',
JSON.stringify({
longitude: location.coords.longitude,
latitude: location.coords.latitude,
checkin: new Date(),
loja: {id: loja.id},
})
);
// object gets filled accondingly
formData.append('imagecheckin', {
uri: checkin.uri,
name: 'imagem.jpg', // I know the image is .jpg
type: 'image/jpg',
});
// imagecheckin is a object inside formData (not a readStream as it normally would)
console.log(formData);
try {
const response = await fetch(`${Endpoint.baseAddr}${Endpoint.visitas}`, {
body: formData,
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer ' + await AsyncStorage.getItem('jwt'),
},
})
.then(res => res.json());
console.log(response);
} catch (err) {
console.error('Erro ao postar a visita! Erro causado:', err);
console.log(err.res, err.response);
}
} catch (err) {
console.error('Erro ao criar a visita! Erro causado:');
console.error(err);
}
}
[…]
ControllerImagens.java
[…]
#PostMapping
public ResponseEntity<T> adicionarCheckin(
#RequestPart(name = "imagecheckin", required = true) MultipartFile file,
#RequestPart(name = "object", required = true) T objeto,
#RequestHeader("authorization") String token) {
// Calls constructors, validators and stuff
[…]
And the formdata I get from the log is
FormData {
"_parts": Array [
Array [
"object",
"{\"longitude\":-40.3097038,\"latitude\":-20.3758293,\"checkin\":\"2020-04-29T18:06:22.994Z\",\"loja\":{\"id\":1}}",
],
Array [
"imagecheckin",
Object {
"name": "imagem.jpg",
"type": "image/jpg",
"uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fproatend-f576a9db-3f86-4238-8677-3ebbd056f4ea/Camera/1f2192a7-fe81-40d1-8efd-9ff6a98a32a3.jpg",
},
],
],
}

CKEditor Upload Adapter Sends [object Promise] to Server

I have been trying to implement CKEditor5 into a vuejs project and after getting all the infrastructure working, I cannot get the actual file to upload to a php server. The code calls the server and if I return a success message and file url, it all works correctly. Here is my code:
<template>
...
<ckeditor :editor="editor" v-model="details.SystemText" :config="editorConfig"></ckeditor>
...
</template>
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
class UploadAdapter {
constructor(loader) {
this.loader = loader;
}
upload() {
return new Promise((resolve, reject) => {
const data = new FormData();
data.append('upload', this.loader.file);
axios({
url: '/index/uploadimage',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data;'
},
withCredentials: false
}).then(response => {
if (response.data.result == 'success') {
resolve({
default: response.data.url
});
} else {
reject(response.data.message);
}
}).catch(response => {
reject ( 'Upload failed');
});
});
}
abort() {
}
}
export default {
data () {
details: {},
editor: ClassicEditor,
editorConfig: {
extraPlugins: [ this.MyCustomUploadAdapterPlugin ],
}
},
methods: {
MyCustomUploadAdapterPlugin ( editor ) {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
return new UploadAdapter( loader );
};
},
}
Clicking the image icon in the toolbar will show the file select dialogue correctly, and upon file selection will submit a post to the server. However, the binary file is not sent, but simply:
Form Data
------WebKitFormBoundaryqPGA20WRKz9VvADd
Content-Disposition: form-data; name="upload"
[object Promise]
I have spent two days looking at all other plugins like CKFinder and others, and I seem to always get the same content being sent to the server. The line
data.append('upload', this.loader.file);
does not seem to append the actual file which is what I think it should do.
My value of this.loader is
loader.file
Promise {<pending>}
__proto__: Promise
catch: ƒ catch()
constructor: ƒ Promise()
finally: ƒ finally()
then: ƒ then()
Symbol(Symbol.toStringTag): "Promise"
__proto__: Object
[[PromiseStatus]]: "pending"
[[PromiseValue]]: undefined
Tried using their cloudservice but point to my own urls and that got the upload working.
editorConfig: {
cloudServices: {
tokenUrl: '/index/tokenendpoint',
uploadUrl: '/index/uploadimage'
}
}
I was also able to remove all the upload adapter code.
Thank you
Reason for your problem is that in version 11.0.0 of ckeditor5-upload plugin the API was changed, loader.file is now a Promise (see release notes). Unfortunately the docs were not updated accordingly.
You need to adjust your upload function a little:
upload() {
return this.loader.file
.then( uploadedFile => {
return new Promise( ( resolve, reject ) => {
const data = new FormData();
data.append( 'upload', uploadedFile );
axios( {
url: '/index/uploadimage',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data;'
},
withCredentials: false
} ).then( response => {
if ( response.data.result == 'success' ) {
resolve( {
default: response.data.url
} );
} else {
reject( response.data.message );
}
} ).catch( response => {
reject( 'Upload failed' );
} );
} );
} );
}
The docs that had this issue are now fixed and use promise properly. Hope this solves the problem for you!
Use jQuery ajax. I cannot find an equivalent using fetch or axios. The key is setting contentType: false and processData: false.
upload() {
return new Promise((resolve, reject) => {
const data = new FormData();
data.append('postedFile', this.loader.file);
$.ajax({
url: '/index/uploadimage',
data,
contentType: false,
processData: false,
type: 'POST',
success: response => {
resolve({
default: response.data.url
});
},
error: () => {
reject('Upload failed');
}
});
});
}
They are working on it, it is a bug.
https://github.com/ckeditor/ckeditor5/issues/1618

vuejs+vue2dropzone call on success

i am quite new in vuejs, so cant find out what am i doing wrong. This is my script part for a vue component:
<script>
export default {
name: 'product-main-info',
components: {
vueDropzone: vue2Dropzone
},
props: {
propId: String,
},
data() {
return {
images: {},
dropzoneOptions: {
url: '/uploadImg',
thumbnailWidth: 150,
maxFilesize: 2.0,
addRemoveLinks: true,
acceptedFiles: ".png,.jpg,.gif,.bmp,.jpeg",
headers: { "X-CSRF-Token": document.head.querySelector('meta[name="csrf-token"]').content },
params: { id: this.propId },
init: function() {
var self = this;
self.on("success", function (file) {
this.$http.get('/getProductImages/' + this.propId)
.then(function(response) {
this.images = response.data;
});
});
}
}
}
},
methods: {
},
created() {
this.$http.get('/getProductImages/' + this.propId)
.then(function(response) {
console.log(response.data);
this.images = response.data;
});
}
}
</script>
I am trying to get new refreshed data after successful image upload, but all i get is:
app.js:16014 Uncaught TypeError: Cannot read property 'get' of undefined
All i need is to refresh my data, but i cant find out how to do this in a right way. Help if possible

How to send an ajax contact form with to a recipient email address

I've currently got this:
$.ajax({
url: '/some/url',
dataType: 'json',
type: 'POST',
data: formData,
success: function(data) {
if (window.confirm('Thank you for your message. Can I erase the form?')) {
document.querySelector('.form-input').val('');
}
},
error: function(xhr, status, err) {
console.error(status, err.toString());
alert('There was some problem with sending your message.');
}
});
Instead of it going to a URL, how can I change it to send directly to a specific email address? I am using this contact form with a React app I've created.
So react component, class based.
class Foo extends Component {
popupQuestion() {
// implement method
}
sendEmail() = () => {
axios.post('/some/url', {
subject: 'mail',
to: 'someone#example.com',
body: 'something',
name: 'name'
})
.then(function (response) {
popupQuestion();
})
.catch(function (error) {
console.log(error);
return 'Error occurred. Please refresh page and try again.';
});
}
render() {
return(
<form onSubmit={this.sendEmail}>
// ...
</form>
);
}
}
And php method that will be executed on some/url
public function sendEmailAction(): bool
{
$request = // get request;
$subject = $request->get('subject');
$to = $request->get('to');
$body = $request->get('body');
$name = $request->get('name');
$transport = (new Swift_SmtpTransport('smtp.example.org', 25))
->setUsername('your username')
->setPassword('your password');
$mailer = new Swift_Mailer($transport);
$message = (new Swift_Message($subject))
->setFrom(['mymail#exmaple.com' => 'me'])
->setTo([$to => $name])
->setBody($body);
$sent = $mailer->send($message);
return $sent ? true : false;
}

Resources