Laravel send image from vue to controller - laravel

I'm trying to save an image when updating an item but I'm having trouble sending the file to the controller in order to save it. This is how I'm sending it
submit(item) {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.loading = true;
this.$inertia.post('/courses/' + item.id, {
name: this.ruleForm.name,
summary: this.ruleForm.summary,
description: this.ruleForm.description,
price: this.ruleForm.price,
hours: this.ruleForm.hours,
min_grade: this.ruleForm.min_grade,
file: this.imagen,
matery: this.matery,
remover: this.remover,
strict: this.strict
}).then(
() => {
this.$message({
type: 'success',
message: 'Guardado correctamente.'
});
this.loading = false
},
(res) => {
this.$message.error(parseError(res)[0]);
this.loading = false;
})
} else {
return false;
}
});
},
If I {{imagen}} and {{imageUrl}} in the vue this is the result respectively, this is why I'm sending the imagen and not the url
[object File]
blob:http://dev.inae.com/9c77fa72-b778-45c9-8ab2-0a9084282415
When I Log::info($request) this is the output, when adding a file and changing text and saving,
local.INFO: array (
'name' => 'Principiante Clase 3 (automático)',
'summary' => 'Enseñaremos a compresionar el vehículo y la utilización de
cambios en vehículo automático',
'description' => '<p>Enseñaremos a compresionar el vehículo y la utilización de
cambios en vehículo automático (viaje a fraijanes).</p>',
'price' => 52000,
'hours' => 2,
'min_grade' => 70,
'file' =>
array (
'uid' => 1576507762527,
),
'matery' => NULL,
'remover' => false,
'strict' => false,
)
However if I only add the image and don't change anything else, nothing happens in the Log
Code for updating the image in the controller, in the update function
//Log is here
$editCourse = Course::find($id);
$destino = "img/courses";
$link = public_path();
if ($request->hasFile('file')) {
if (!empty($editCourse->image) && file_exists($link . $editCourse->image)) {
unlink($link . $editCourse->image);
}
$image = $request->file('file');
$imageName = Uuid::generate(4)->string . '.' . $image->getClientOriginalExtension();
$editCourse->image = '/' . $destino . '/' . $imageName;
$request->file('file')->move($destino, $imageName);
}
What could I be doing wrong?

You likely need to use the FormData object like so:
let data = new FormData();
data.append('file', this.imagen);
// Attach the other properties.
data.append(...);
$inertia.post(data);
This is because you shouldnt upload files using x-www-form-urlencoded, instead you should be using multipart/form-data which allows you to upload binary data. This also means that the backend will not receive a JSON string anymore, but a form-data response. Laravel should handle this automatically though.

Related

Quasar q-uploader with Laravel not recognizing the file while q-file works

I was able to get q-file to upload a single image and my Laravel API is handling it perfectly. Of course I need multiple files uploaded at once so I'm trying to switch to q-uploader and when I log the response the file shows as [object File].
I also tried using $request->file('attachment') in the FileController but it returns null.
<q-uploader
:factory="uploadFactory"
label="Upload Images/Files"
color="primary"
multiple
/>
Then in my FileController.php:
public function upload(Request $request) {
\Log::info($request);
}
returns:
array (
'attachment' => '[object File]',
'fileable_type' => 'App\\Task',
'fileable_id' => '27375',
'vessel_id' => '1',
)
My factory to upload:
uploadFactory (file) {
let data = new FormData()
data.append('attachment', file)
data.append('fileable_type', 'App\\Task')
data.append('fileable_id', this.task.id)
data.append('vessel_id', this.vessel.id)
return new Promise((resolve, reject) => {
this.$axios.post('/api/file/upload', data, { headers: { 'Content-Type': 'multipart/form-data' } }).then(response => {
console.log(response)
resolve(null)
}).catch(error => {
if (error) {
console.log(error)
}
})
})
},
When I try this with the q-file:
<q-file color="primary" v-model="attachments" label="Images/Files" outlined>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after v-if="canUpload">
<q-btn
color="primary"
dense
icon="cloud_upload"
round
#click="submitFiles"
:disable="!canUpload"
:loading="isUploading"
/>
</template>
</q-file>
It works and here's what I'm logging in Laravel for the request:
array (
'fileable_type' => 'App\\Task',
'fileable_id' => '27375',
'vessel_id' => '1',
'attachments' =>
Illuminate\Http\UploadedFile::__set_state(array(
'test' => false,
'originalName' => 'IMG_0126.jpg',
'mimeType' => 'image/jpeg',
'error' => 0,
'hashName' => NULL,
)),
)
probably you got the answer to this question already.
But here is what I did. I had the same issue from q-uploader, send one file to laravel, and everything is OK. But I got stuck when sending multiple files. I had to consult info from various sources to arrange the hole process.
So what I did is this:
On my frontend:
<q-uploader
:factory="uploadFiles"
:loading="uploadPercent"
:url="getUrl()"
#finish="finished"
label="Cargar Archivos (max 2MB)"
ref="uploader"
multiple
bordered
batch
accept=".png, .jpeg, .jpg, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .csv, .pdf, pdf/*, image/*"
:max-file-size="2048000"
/>
On my method:
uploadFiles(file){
this.uploadPercentage = true
let files = file
console.log(files)
let files_count = files.length + this.files.length
if(files_count > 10){
this.Notify(`El límite de archivos por tarea es de 10`,'negative')
this.finished()
return
}
const data = new FormData()
for(var i = 0; i < files.length; i++){
let file = files[i]
data.append(`files[${i}]`, file)
}
data.append('teacher', this.teacher)
data.append('homework', this.homework)
return new Promise((resolve, reject) => {
this.$axios.post(`${process.env.API}/homework/upload-files`, data,
{
headers: { 'content-type': 'multipart/form-data' },
processData: false, contentType: false
})
.then(res => {
resolve(null)
this.uploadPercentage = false
this.files = res.data
this.Notify('Se subieron los archivos con éxito','positive')
})
.catch(err => {
reject(err)
this.errors = err.response.data.errors
this.uploadPercentage = false
this.Notify('No se pudieron cargar los archivos, o el formato de alguno de los archivos no es correcto, o alguno de los archivos pesa más de 2MB','negative')
})
})
},
And on my backend function, I only store the file (I'am storing it on the public folder instead of storage, because I have a shared hosting on this project), additionally you can add some code to save the file location to your Database:
public function upload_files(Request $request)
{
$homework = DB::table('homeworks as h')
->join('teachers as t','t.id','=','h.teacher_id')
->join('users as u','u.id','=','t.teacher_id')
->select('h.id')
->where('h.code','=',$request->homework)
->where('u.code','=',$request->teacher)
->first();
if(!$homework){
return response()->json(['success'=>false,'msg'=>'Not avalid homework'],422);
}
try{
DB::beginTransaction();
$files = $request->file('files');
if(!empty($files)){
for($i = 0; $i < count($files); $i++){
$file = $files[$i];
$filename = $request->homework.'_'.uniqid('doc_').'.'.$file->getClientOriginalExtension();
$path = public_path('/uploads');
$file->move($path, $filename);
}
}
DB::commit();
return response()->json(['success' => true], 200);
}
catch (\Exception $e)
{
DB::rollback();
throw $e;
}
}

Form Data file return null in laravel/lumen when using axios from react native

It's my first time using React Native and Laravel.
I am trying to create an upload form in React Native to Lumen API.
When I try to upload file to Lumen using Postman, it works fine. But when using Axios in React Native:
$request->file('file')
returns
null
public function store(Request $request) {
$this->validate($request, [
"file" => 'required|file',
"from" => 'required',
"to" => 'required',
"subject" => 'required',
"doc_date" => 'required',
"doc_type" => 'required',
"doc_number" => 'required',
]);
$file = $request->file('file');
$fileName = $file->getClientOriginalName();
$saved_name = uniqid() . '_' . $fileName;
$path = "uploads" . DIRECTORY_SEPARATOR . "documents" . DIRECTORY_SEPARATOR;
$file->move($path, $saved_name);
$document = new Document();
$document->from = $request->input("from");
$document->to = $request->input("to");
$document->subject = $request->input("subject");
$document->doc_date = $request->input("doc_date");
$document->doc_type = $request->input("doc_type");
$document->doc_number = $request->input("doc_number");
$document->file_path = $path . $saved_name;
$document->save();
return response()->json(['document' => $document], 201);
}
## Client
async uploadDocument(document, file) {
// document is some form data
// document: {
// from: 'me#mail.com',
// to: 'someone#gmail.com',
// doc_date: '2020-02-01',
// ....
// }
// file from react-native-document-picker
// file: {
// fileName: 'blablabla.pdf',
// type: 'blablabla/blabla',
// uri: 'content://blablabla',
// }
let resp;
try {
resp = await axios.post(
`${API_ENDPOINT}/documents`,
helper.createFormData(file, document),
{
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
},
);
} catch (e) {
console.log(`Axios error: ${e.message}`);
throw e;
}
console.log(`Server response: ${JSON.stringify(resp.data)}`);
return resp;
},
## Helper
export default {
createFormData(file, body) {
const data = new FormData();
data.append('file', {
name: file.fileName,
type: file.type,
uri: file.uri,
});
Object.keys(body).forEach(key => {
data.append(key, body[key]);
});
return data;
},
};

cakephp2 can't get file data array through $this->request->data

usually, we get all the data we need from $this->request->data. but if I'm using ajax file upload, I can't get that data e.g: tmp_name, size, etc.
my javascript code is like:
function uploadFile(file_blob_chunk, file_name, file_part, total_file_chunk, file_id) {
fd = new FormData();
fd.append("file_for_upload", file_blob_chunk);
fd.append("somestring", "This is some extra data");
xhr = new XMLHttpRequest();
xhr.open("POST", "files/index/" + file_id + '/' + file_part, true);
//Onload happened after file finished uploaded
xhr.onload = function(e) {
//alert(file_name + "done");
};
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
}}, false);
xhr.send(fd);
}
and in FilesController.php
public function index($file_id = null, $file_part = null) {
if ($this->request->is('post')) {
//I can't use $this->request->data, to get the file details
}
}
If I use
debug($this->request->data);
I will only get
array(
'somestring' => 'This is some extra data'
)
I can't get the file data
Unless Im using debug($_FILES), I won't get
array(
'file_for_upload' => array(
'name' => 'blob',
'type' => 'application/octet-stream',
'tmp_name' => 'C:\xampp\tmp\phpAC42.tmp',
'error' => (int) 0,
'size' => (int) 9304862
)
)
If you want to use $this->request->data your post data should be in the format cake expects, eg: data[Model][some_field]
you have CustomField

Magento custom image upload doesn't work

I need to create an image upload field for posts in Magento Blog Module (AW blog).
Therefore, each post needs to contain an image.
I edited the following files:
/home/clients/websites/w_gale/public_html/gale/app/code/community/AW/Blog/Block/Manage/Blog/Edit/Tab/Form.php
added fieldset like this:
$fieldset->addField('fileinputname', 'image', array(
'label' => Mage::helper('blog')->__('Upload image'),
'required' => false,
'name' => 'fileinputname',
'required' => true,
'style' => 'height:100px;border:2px solid #999;',
));
on top of this file, in the right place, I defined form like this:
$form = new Varien_Data_Form(array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
'method' => 'post',
'enctype' => 'multipart/form-data',
)
);
In Blogcontroller.php I added the following code, just bellow the if ($data = $this->getRequest()->getPost()) { line
if(isset($_FILES['fileinputname']['name']) && (file_exists($_FILES['fileinputname']['tmp_name']))) {
try {
$uploader = new Varien_File_Uploader('fileinputname');
$uploader->setAllowedExtensions(array('jpg','jpeg','gif','png')); // or pdf or anything
$uploader->setAllowRenameFiles(true);
$uploader->setFilesDispersion(false);
$path = Mage::getBaseDir('media') . DS ;
$uploader->save($path, $_FILES['fileinputname']['name']);
$data['imageurl'] = $_FILES['fileinputname']['name'];
} catch(Exception $e) {
}
} else {
if(isset($data['fileinputname']['delete']) && $data['fileinputname']['delete'] == 1)
$data['imageurl'] = '';
else
unset($data['fileinputname']);
}
However, the upload doesn't work. What am I doing wrong?
I added a special row in appropriate field in a database.
The frontend section displays the database value when I enter it manually.
Thanks
This code of method from data helper which uploads image. You need implement method getBaseDir() (which returns dir where you wish store your uploaded files) by yourself.
/**
* Upload image and return uploaded image file name or false
*
* #throws Mage_Core_Exception
* #param string $scope the request key for file
* #return bool|string
*/
public function uploadImage($scope)
{
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator('ImageSize', true, $this->_imageSize);
$adapter->addValidator('Size', true, $this->_maxFileSize);
if ($adapter->isUploaded($scope)) {
// validate image
if (!$adapter->isValid($scope)) {
Mage::throwException(Mage::helper('mycompany_mymodule')->__('Uploaded image is not valid'));
}
$upload = new Varien_File_Uploader($scope);
$upload->setAllowCreateFolders(true);
$upload->setAllowedExtensions(array('jpg', 'gif', 'png'));
$upload->setAllowRenameFiles(true);
$upload->setFilesDispersion(false);
if ($upload->save($this->getBaseDir())) {
return $upload->getUploadedFileName();
}
}
return false;
}
You're using the right code. I solved the problem by using the right MYSQL data type. When I changed the data type from 'text' to 'varchar(255)' it solved the problem
And ... make sure that you add the following code:
$form = new Varien_Data_Form(array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
'method' => 'post',
'enctype' => 'multipart/form-data',
)
);
in /app/code/community/AW/Blog/Block/Manage/Blog/Edit/Form.php
NOT: app/code/community/AW/Blog/Block/Manage/Blog/Edit/Tab/Form.php

Wordpress nonce check always false

I'm having problems with a basic nonce validation via an ajax request.
Those are my script loader and css loader functions:
(in gallery.php)
function gallery_js_loader()
{
if (!is_admin()) return;
// async flash uploader
wp_enqueue_script('swfobject', THEMEURL . "/lib/uploadify/swfobject.js", array(), false, true);
wp_enqueue_script('uploadify', THEMEURL . "/lib/uploadify/jquery.uploadify.v2.1.4.min.js", array('jquery'), false, true);
wp_enqueue_script('gallery_admin_scripts', THEMEURL . "/inc/galleries/gallery_admin_scripts.js", array(), false, true);
wp_localize_script('gallery_admin_scripts', 'param',
array(
'basename' => GALLERYPOST,
'baselocation' => THEMEURL,
'nonce' => wp_create_nonce('file-upload-nonce'),
'thumb_width' => intval(get_option('thumbnail_size_w')),
'thumb_height' => intval(get_option('thumbnail_size_h'))
));
// main styles
}
function gallery_css_loader()
{
wp_enqueue_style('uploadify_styles', THEMEURL . "/lib/uploadify/uploadify.css");
wp_enqueue_style('gallery_admin_styles', THEMEURL . "/inc/galleries/gallery_admin_styles.css");
}
add_action('admin_print_scripts-post.php', 'gallery_js_loader');
add_action('admin_print_scripts-post-new.php', 'gallery_js_loader');
add_action('admin_print_styles-post.php', 'gallery_css_loader');
add_action('admin_print_styles-post-new.php', 'gallery_css_loader');
function gallery_upload_image()
{
$nonce = $_POST["nonce"];
if (is_admin() && !empty($_FILES) /*&& wp_verify_nonce($nonce, 'file-upload-nonce')*/) {
require_once(ABSPATH . 'wp-admin/includes/image.php');
$tempFile = $_FILES['Filedata']['tmp_name'];
// $targetPath = $_SERVER['DOCUMENT_ROOT'] . $_REQUEST['folder'] . '/';
$targetDir = wp_upload_dir(date('Y'));
$targetFile = $targetDir['path'] . '/' . $_FILES['Filedata']['name'];
$targetFile = str_replace(" ", "", $targetFile);
move_uploaded_file($tempFile, $targetFile);
$wp_filetype = wp_check_filetype(basename($targetFile), null);
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($targetFile)),
'post_content' => '',
'post_status' => 'inherit'
);
$result['attachmet_id'] = $attach_id = wp_insert_attachment($attachment, $targetFile);
$result['recieved_nonce'] = $nonce;
$attach_data = wp_generate_attachment_metadata($attach_id, $targetFile);
wp_update_attachment_metadata($attach_id, $attach_data);
$result['success'] = true;
} else {
$result['success'] = false;
$result['recieved_nounce'] = $nonce;
$result['error'] = array(
'message' => 'No files or you are not admin ' . $nonce,
'code' => 'E01'
);
}
echo json_encode($result);
exit;
}
add_action('wp_ajax_do_upload', 'gallery_upload_image');
In my javascrtip file:
(in gallery.js)
console.debug("Nonce received ",param.nonce); //c4817b947a
My ajax call will access a do_upload action from php. This one will append the received nonce field to the response...
(back in gallery.php)
function gallery_upload_image()
{
$nonce = $_POST["nonce"];
if ( wp_verify_nonce($nonce, 'file-upload-nonce')) {
/* some logic here, nothing to do with nonce */
$result['success'] = true;
$result['debugNonce'] = $nonce;
} // end validation
else {
//invalid nonce
$result['success'] = false;
$result['debugNonce'] = $nonce;
}
}
The received result looks like this:
c4817b947a {"success":false,"debugNonce":"c4817b947a"}
The first c4817b947a is because of the echo from the nonce generation function. It does not influence the way the validation happens.
My conclusion is that wp_verify_nonce always fails.
I am using wp 3.2.1 on localhost, fresh install, no plugins.
I've just ran into a similar issue and it turned out that all I had to do is to re-log as admin. I think it should also work in your case, because everything else in the provided code seems to be fine.
I guess it has something to do with how sessions are handled in Wordpress.
I do an almost identical interchange without problems.
This is in a plugin (class), but that shouldn't matter.
PHP - initialize the javascript :
add_action( 'wp_print_scripts', array( &$this, 'enqueue_script') );
PHP - function enqueue_script:
wp_localize_script( 'B99-Portfolio', 'ajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ),
'imgurl' => content_url().'/uploads/portfolio-content/',
'requestNonce' => wp_create_nonce('b99-request-nonce')) );
JS - initiate the ajax request:
$.ajax({
type : 'POST',
cache : false,
url : ajax.ajaxurl,
data : {
action : 'b99_ajax_request_items',
requestNonce : ajax.requestNonce
},
dataType: 'json',
error : function(jqXHR, textStatus, errorThrown) {alert(jqXHR+" "+textStatus+" "+errorThrown);},
success : function( response ) {recieveAjax( response );}
});
PHP - recieve and handle the request ( function b99_ajax_request_items):
$nonce = $_POST['requestNonce'];
if ( ! wp_verify_nonce( $nonce, 'b99-request-nonce' ) ){
die ( 'security fail'.$nonce);
}
Make sure that you have enqueued the script prior to localizing it.
I'm using current versions of both jquery and wordpress and this works seamlessly on a local install of XAMPP. It looks pretty similar to your interchange, but maybe this is something to compare against.

Resources