Saving blob image in laravel's controller - laravel-5

In my Laravel 5/vuejs 2.6 I upload an image with the vue-upload-component and am sending a requested image blob
I try to save it with the controller code like :
if ( !empty($requestData['avatar_filename']) and !empty($requestData['avatar_blob']) ) {
$dest_image = 'public/' . Customer::getUserAvatarPath($newCustomer->id, $requestData['avatar_filename']);
$requestData['avatar_blob']= str_replace('blob:','',$requestData['avatar_blob']);
Storage::disk('local')->put($dest_image, file_get_contents($requestData['avatar_blob']));
ImageOptimizer::optimize( storage_path().'/app/'.$dest_image, null );
} // if ( !empty($page_content_image) ) {
As result, I have an image uploaded, but it is not readable.
The source file has 5 Kib, the resulting file has 5.8 Kib and in the browser's console I see the blobs path as
avatar_blob: "blob:http://local-hostels2.com/91a18493-36a7-4023-8ced-f5ea4a3c58af"
Have do I convert my blob to save it correctly?
MODIFIED :
a bit more detailed :
In vue file I send request using axios :
let customerRegisterArray =
{
username: this.previewCustomerRegister.username,
email: this.previewCustomerRegister.email,
first_name: this.previewCustomerRegister.first_name,
last_name: this.previewCustomerRegister.last_name,
account_type: this.previewCustomerRegister.account_type,
phone: this.previewCustomerRegister.phone,
website: this.previewCustomerRegister.website,
notes: this.previewCustomerRegister.notes,
avatar_filename: this.previewCustomerRegister.avatarFile.name,
avatar_blob: this.previewCustomerRegister.avatarFile.blob,
};
console.log("customerRegisterArray::")
console.log(customerRegisterArray)
axios({
method: ('post'),
url: window.API_VERSION_LINK + '/customer_register_store',
data: customerRegisterArray,
}).then((response) => {
this.showPopupMessage("Customer Register", 'Customer added successfully ! Check entered email for activation link !', 'success');
alert( "SAVED!!::"+var_dump() )
}).catch((error) => {
});
and this.previewCustomerRegister.avatarFile.blob has value: "blob:http://local-hostels2.com/91a18493-36a7-4023-8ced-f5ea4a3c58af"
where http://local-hostels2.com is my hosting...
I set this value to preview image defined as :
<img
class="img-preview-wrapper"
:src="previewCustomerRegister.avatarFile.blob"
alt="Your avatar"
v-show="previewCustomerRegister.avatarFile.blob"
width="256"
height="auto"
id="preview_avatar_file"
>
and when previewCustomerRegister.avatarFile.blob is assigned with uploaded file I see it in preview image.
I show control with saving function in first topic but when I tried to opened my generated file with kate, I found that it
has content of my container file resources/views/index.blade.php...
What I did wrong and which is the valid way ?
MODIFIED BLOCK #2 :
I added 'Content-Type' in request
axios({
method: ('post'),
url: window.API_VERSION_LINK + '/customer_register_store',
data: customerRegisterArray,
headers: {
'Content-Type': 'multipart/form-data'
}
but with it I got validation errors in my control, as I define control action with request:
public function store(CustomerRegisterRequest $request)
{
and in app/Http/Requests/CustomerRegisterRequest.php :
<?php
namespace App\Http\Requests;
use App\Http\Traits\funcsTrait;
use Illuminate\Foundation\Http\FormRequest;
use App\Customer;
class CustomerRegisterRequest extends FormRequest
{
use funcsTrait;
public function authorize()
{
return true;
}
public function rules()
{
$request= Request();
$requestData= $request->all();
$this->debToFile(print_r( $requestData,true),' getCustomerValidationRulesArray $requestData::');
/* My debugging method to write data to text file
and with Content-Type defined above I see that $requestData is always empty
and I got validations errors
*/
// Validations rules
$customerValidationRulesArray= Customer::getCustomerValidationRulesArray( $request->get('id'), ['status'] );
return $customerValidationRulesArray;
}
}
In routes/api.php defined :
Route::post('customer_register_store', 'CustomerRegisterController#store');
In the console of my bhrowser I see : https://imgur.com/a/0vsPIsa, https://imgur.com/a/wJEbBnP
I suppose that something is wrong in axios header ? without 'Content-Type' defined my validation rules work ok...
MODIFIED BLOCK #3
I managed to make fetch of blob with metod like :
var self = this;
fetch(this.previewCustomerRegister.avatarFile.blob) .then(function(response) {
console.log("fetch response::")
console.log( response )
if (response.ok) {
return response.blob().then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
// myImage.src = objectURL;
console.log("objectURL::")
console.log( objectURL )
console.log("self::")
console.log( self )
let customerRegisterArray =
{
username: self.previewCustomerRegister.username,
email: self.previewCustomerRegister.email,
first_name: self.previewCustomerRegister.first_name,
last_name: self.previewCustomerRegister.last_name,
account_type: self.previewCustomerRegister.account_type,
phone: self.previewCustomerRegister.phone,
website: self.previewCustomerRegister.website,
notes: self.previewCustomerRegister.notes,
avatar_filename: self.previewCustomerRegister.avatarFile.name,
avatar: objectURL,
};
console.log("customerRegisterArray::")
console.log(customerRegisterArray)
axios({
method: 'POST',
url: window.API_VERSION_LINK + '/customer_register_store',
data: customerRegisterArray,
// headers: {
// 'Content-Type': 'multipart/form-data' // multipart/form-data - as we need to upload with image
// }
}).then((response) => {
self.is_page_updating = false
self.message = ''
self.showPopupMessage("Customer Register", 'Customer added successfully ! Check entered email for activation link !', 'success');
alert( "SAVED!!::")
}).catch((error) => {
self.$setLaravelValidationErrorsFromResponse(error.response.data);
self.is_page_updating = false
self.showRunTimeError(error, this);
self.showPopupMessage("Customer Register", 'Error adding customer ! Check Details fields !', 'warn');
// window.grecaptcha.reset()
self.is_recaptcha_verified = false;
self.$refs.customer_register_wizard.changeTab(3,0)
});
});
} else {
return response.json().then(function(jsonError) {
// ...
});
}
}).catch(function(error) {
console.log('There has been a problem with your fetch operation: ', error.message);
});
In objectURL and self I see proper values : https://imgur.com/a/4YvhbFz
1) But checking data on server in laravel's control I see the same values I had at start of my attemps to upload image:
[avatar_filename] => patlongred.jpg
[avatar] => blob:http://local-hostels2.com/d9bf4b66-42b9-4990-9325-a72dc8c3a392
Have To manipulate with fetched bnlob in some other way ?
2) If I set :
headers: {
'Content-Type': 'multipart/form-data'
}
I got validation errors that my data were not correctly requested...
?

You're using request type as application/json hence you won't be able to save the image this way, for a file upload a request type should be multipart/form-data in this case you'll need to send request as
let customerRegisterArray = new FormData();
customerRegisterArray.put('username', this.previewCustomerRegister.username);
customerRegisterArray.put('email', this.previewCustomerRegister.email);
....
customerRegisterArray.put('avatar', this.previewCustomerRegister.avatarFile);
console.log("customerRegisterArray::")
console.log(customerRegisterArray)
axios({
method: ('post'),
url: window.API_VERSION_LINK + '/customer_register_store',
data: customerRegisterArray,
headers: {
'Content-Type': 'multipart/form-data'
}
}).then((response) => {
this.showPopupMessage("Customer Register", 'Customer added successfully !Check entered email for activation link !', 'success');
alert( "SAVED!!::"+var_dump() )
}).catch((error) => {});

Thank you for your help!
Valid decision was :
var self = this;
fetch(this.previewCustomerRegister.avatarFile.blob) .then(function(response) {
if (response.ok) {
return response.blob().then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
let data = new FormData()
data.append('username', self.previewCustomerRegister.username)
data.append('email', self.previewCustomerRegister.email)
data.append('first_name', self.previewCustomerRegister.first_name)
data.append('last_name', self.previewCustomerRegister.last_name)
data.append('account_type', self.previewCustomerRegister.account_type)
data.append('phone', self.previewCustomerRegister.phone)
data.append('website', self.previewCustomerRegister.website)
data.append('notes', self.previewCustomerRegister.notes)
data.append('avatar_filename', self.previewCustomerRegister.avatarFile.name)
data.append('avatar', myBlob)
axios({
method: 'POST',
url: window.API_VERSION_LINK + '/customer_register_store',
data: data,
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data' // multipart/form-data - as we need to upload with image
}
}).then((response) => {
self.is_page_updating = false
self.message = ''
self.showPopupMessage("Customer Register", 'Customer added successfully ! Check entered email for activation link !', 'success');
alert( "SAVED!!::123")
// self.$router.push({path: '/'});
}).catch((error) => {
self.$setLaravelValidationErrorsFromResponse(error.response.data);
self.is_page_updating = false
self.showRunTimeError(error, this);
self.showPopupMessage("Customer Register", 'Error adding customer ! Check Details fields !', 'warn');
window.grecaptcha.reset()
self.is_recaptcha_verified = false;
self.$refs.customer_register_wizard.changeTab(3,0)
});
});
} else {
return response.json().then(function(jsonError) {
// ...
});
}
}).catch(function(error) {
console.log('There has been a problem with your fetch operation: ', error.message);
});
and common laravel's file uploading functionality :
$customerAvatarUploadedFile = $request->file('avatar');
...

Related

how do I get the section title, sub_section_title and file in the formData in laravel

I am developing an application using laravel 8 and vuejs. I am trying to post form data from my vuejs to backend(laravel) but it is not working
The vuejs creates a subsection of a section which is add to an array of subsection inside the section array which is converted to string and added to a form data then sent as a request to my backend.
The frontend is working perfectly well but I cant access the data on my backend. How do I get the values of the course title, section title, sub section title and file added
Vuejs
<script>
import { reactive } from "vue";
import axios from "axios";
export default {
name: 'CreateCourse',
setup(){
const sections = reactive([{'section_title': '', 'sub_sections': [{'sub_section_title': '', 'file': '', 'url': ''}]}]);
const course = reactive({'title': '', 'description': ''});
const addSection = () => {
sections.push({"section_title": "", 'sub_sections': [{'sub_section_title': '', 'file': '', 'url': ''}]});
}
const addSubSection = (idx) => {
console.log('the value of idx is ', idx);
sections[idx].sub_sections.push({"sub_section_title": "", 'file': '', 'url': ''});
}
const uploadFile = (e, idx, i) => {
sections[idx].sub_sections[i].file = e.target.files[0];
sections[idx].sub_sections[i].url = URL.createObjectURL(sections[idx].sub_sections[i].file);
}
const createCourse = (e) => {
e.preventDefault();
let newCourse = JSON.stringify(course)
let newSection = JSON.stringify(sections)
const formData = new FormData();
formData.append("course", newCourse);
formData.append("sections", newSection);
showLoader(true);
axios.post('/api', form, { headers: {'Content-Type': 'multipart/form-data'}}).then(response =>
{
NotificationService.success(response.data.message);
showLoader(false);
course.title = '';
course.description = '';
}).catch(err => {
NotificationService.error(err.response);
showLoader(false);
});
}
return {
course,
createCourse,
sections,
addSection,
addSubSection,
uploadFile
}
}
</script>
laravel code
echo $request->get("title");
echo $request->get("description");
foreach($request->section_title as $titles)
{
echo $titles
}
foreach($request->section_sub_title as $sub_titles)
{
// info($sub_titles);
// return $sub_titles;
echo $sub_titles
}
{"course":{"title":"Frontend","description":"This is building web interface with html, css and javascript"},"sections":[{"section_title":"HTML","sub_sections":[{"sub_section_title":"What is HTML","file":{},"url":"blob:http://localhost:8080/ea0acc7d-34e6-4bff-9255-67794acd8fab"}]}]}
Bit tricky to understand where you're stuck, but let's give it a shot:
Does the api request actually reach your route (post -> /api), do you see in the network tab a post request to the route?
Have you tried running dd($request->all()) in the controller method so see what you're getting (just do this on the first line inside your method)?
Small gotcha moment:
Sometimes it helps to run the php artisan route:clearcommand

Cannot upload image to laravel from react-native

I'm trying to let the user upload an image through react-native, but apparently, laravel is not being able to read any value from the request. This is what I'm trying to do with axios:
const data = new FormData()
data.append('subject_id', this.props.navigation.getParam('id'))
data.append('name', this.state.title)
// I don't think the path is enough, it will probably just send the path as a string instead of the image. You need to load the actual file and append that
data.append('image', {
uri: this.state.image,
type: 'image/jpeg',
name: 'image'
});
data.append('progress', this.state.progress * 100)
data.append('description', this.state.description)
data.append('date', this.state.date)
axios.post('https://example.com/api/auth/storeTask', data, {
headers: {
'Authorization': access,
"Content-Type": "multipart/form-data"
},
}).then(result => { })
.catch(err => console.warn)
The image is not found when I try to access the resource.
You should use a FormData object:
const data = new FormData()
data.append('subject_id', this.props.navigation.getParam('id'))
data.append('name', this.state.title)
// I don't think the path is enough, it will probably just send the path as a string instead of the image. You need to load the actual file and append that
data.append('image', this.state.image)
data.append('progress', this.state.progress * 100)
data.append('description', this.state.description)
data.append('date', this.state.date)
axios.post('https://example.com/api/auth/storeTask', data, {
headers: {
'Authorization': access,
"Content-Type": "multipart/form-data"
},
}).then(result => {})
.catch(err => console.warn)
You didn't send complete info like responses and logs, by the way,
Please check this instruction:
make sure your CSRF in verifyCSRFtoken is allowed
use FormData to upload your file
your code coulde be like this:
import axios, { post } from 'axios';
const url = '/uploadPic';
const formData = new FormData();
formData.append("image", {
name: this.state.photo.fileName,
type: this.state.photo.type,
uri: this.state.photo.uri,
});
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
return post(url, formData,config)
for react native:
if you are in production and using react-native bare, you should add
<application
...
android:usesCleartextTraffic="true"
...
to your android file.

how to upload image in register API in strapi?

In defaut registration API, I need to uplaod the image of user in registration API. So how could I manage it ? I'm sending in a formData and it works fine. I can see (binary) in network.
I tried to add image field and it works in admin panel but from API side I tried to send the file in key names like files, profileImage.
I didn't get the error in res. I got success in res.
Issue: When I reload the admin panel, I didn't get user's profile image.
Try this way. I used in react and it works fine for me.
signUpHandler = () => {
console.log("SignUp data ::: ", this.state);
let data = {
username: this.state.signUpForm.username.value,
phone: this.state.signUpForm.phone.value,
email: this.state.signUpForm.email.value,
password: this.state.signUpForm.password.value
}
axios.post('http://0.0.0.0:1337/auth/local/register', data)
.then(res => {
console.log(res);
return res.data.user.id;
})
.then(refId =>{
const data = new FormData();
data.append('files', this.state.selectedFile);
data.append('refId', refId);
data.append('ref', 'user');
data.append('source', 'users-permissions');
data.append('field', 'profileImage');
return axios.post('http://0.0.0.0:1337/upload', data)
})
.then(res =>{
console.log(res);
alert("You registered successfully...");
this.props.history.push('/login');
})
.catch(error =>{
console.log(error);
})
}
First, you will have to customize your user-permission
To do so, you will have to understand this concept: https://strapi.io/documentation/3.0.0-beta.x/concepts/customization.html
Then you will have to find the function you want to update - in your case, the register function.
And tada here it is https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-users-permissions/controllers/Auth.js#L383.
So you will have to create ./extensions/users-permissions/controllers/Auth.js with the same content as the original file.
Then you will have to add
const { parseMultipartData, sanitizeEntity } = require('strapi-utils');
const uploadFiles = require('strapi/lib/core-api/utils/upload-files');
on the top of your file.
And in your function use this
const { data, files } = parseMultipartData(ctx); to parse data and files.
Then you will have to replace ctx.request.body by data to make sure to use the correct data.
After that you will have to add this after the user creation line
https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-users-permissions/controllers/Auth.js#L510
if (files) {
// automatically uploads the files based on the entry and the model
await uploadFiles(user, files, { model: strapi.plugins['users-permissions'].models.user })
}
Solution for Strapi v4:
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer XXXX");
var formdata = new FormData();
formdata.append("files", fileInput.files[0], "XXX.png");
formdata.append("refId", "46");
formdata.append("field", "image");
formdata.append("ref", "plugin::users-permissions.user");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: formdata,
redirect: 'follow'
};
fetch("http://localhost:1337/api/upload", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));

Add custom headers to upload image

I'm currently trying to integrate the CKeditor 5 ReactComponent into my app.
I'm facing an issue with the upload image functionality... I use a Node/Express backend which uses a JWT auth middleware, so each request must have an Authorization header in order to pass.
I want to know if one of the following is possible:
a way to add a custom header to the component
a way to overwrite the upload handler and call a custom handler instead in which I can do what ever
Below is my code
<CKEditor
editor={ClassicEditor}
data="<p>Add product description here</p>"
onInit={(editor) => {
// You can store the "editor" and use when it is needed.
//console.log('Editor is ready to use!', editor);
}}
onChange={(event, editor) => {
const data = editor.getData();
this.handleData(data)
}}
config={{
ckfinder: {
uploadUrl: `${apiUrl}/upload/images/description`,
},
}}
/>
Thanks
try it with this code in property onInit
onInit={ editor => {
editor.plugins.get( 'FileRepository' ).createUploadAdapter = function( loader ) {
return new UploadAdapter( loader );
};
}}
after you must create the class UploadAdapter
class UploadAdapter {
constructor( loader ) {
// Save Loader instance to update upload progress.
this.loader = loader;
}
upload() {
const data = new FormData();
data.append('typeOption', 'upload_image');
data.append('file', this.loader.file);
return new Promise((resolve, reject) => {
axios({
url: `${API}forums`,
method: 'post',
data,
headers: {
'Authorization': tokenCopyPaste()
},
withCredentials: true
}).then(res => {
console.log(res)
var resData = res.data;
resData.default = resData.url;
resolve(resData);
}).catch(error => {
console.log(error)
reject(error)
});
});
}
abort() {
// Reject promise returned from upload() method.
}
}

angular6 - I can't get response from Scopus API

I want to use the Scopus API to verify that a DOI exists. I'm using the "Cited By" option. I did a test of this "http://api.elsevier.com/content/search/scopus?query=DOI(10.1016/j.stem.2011.10.002)" link in POSTMAN and it works, but when I did the implementation in Angular this is what returns.
Angular code
let headers = new Headers({
'X-ELS-APIKey': apikey,
'Accept': 'application/json',
});
this._http.get('http://api.elsevier.com/content/search/scopus?query=DOI(' + doi + ')', { headers: headers }).pipe(map(res => res.json())).subscribe(
response => {
console.log("Response");
console.log(response);
},
error => {
console.log("Error");
console.log(error);
}
);
Any help is greatly appreciated :)
Finally I solved it, the problem was that the "doi" string needed to go through the encodeURIComponent() function. I leave the code in case someone needs it.
welcome.component.ts:
let doi = encodeURIComponent('10.1017/j.stem.2011.10.002');
this._scopusService.getPublication(doi).subscribe(
response => {
console.log("DOI exists");
},
error => {
console.log("DOI doesn't exists");
}
scopus.service.ts:
public getPublication(doi) {
let headers = new Headers({
'Accept': 'application/json',
'X-ELS-APIKey': this.apiKey
});
return this._http.get('https://api.elsevier.com/content/search/scopus?query=DOI(' + doi + ')', { headers: headers }).pipe(map(res => res.json()));
}

Resources