Like the title says, I'm trying to do an image upload from VueJs to a Laravel endpoint. I discovered that the only way(if there is another please tell me) is to send the base64 of the image through the request. On the Vue side I think everything is covered.
However, on the Laravel side is where it gets complicated. I can't decode the base64 string that gets passed, and when I try to store the image in my AWS S3 bucket, it doesn't store properly. Here is the code:
VueJS
<template>
<input type="file" name="image" class="form-control" #change="imagePreview($event)">
</template>
methods: {
submitForm(){
axios.defaults.headers.post['Content-Type'] = 'multipart/form-data';
axios.post(this.$apiUrl + '/article', {
image: this.image
}).then(response => {
flash(response.data.message, 'success');
}).catch(e => {
console.log(e);
})
},
imagePreview(event) {
let input = event.target;
if (input.files && input.files[0]) {
var reader = new FileReader();
let vm = this;
reader.onload = e => {
this.previewImageUrl = e.target.result;
vm.image = e.target.result;
}
reader.readAsDataURL(input.files[0]);
}
}
}
Laravel:
$this->validate($request, [
'image' => 'required',
]);
// return response()->json(base64_decode($request->image));
$timestampName = microtime(true) . '.jpg';
$url = env('AWS_URL') . '/article_images/' .$timestampName;
Storage::disk('s3')->put($timestampName, base64_decode($request->image));
If I add the image validation rule, it says it's not an image..
I would also like to retrieve the extension if possible.
you can do it using FormData in JS part and use getClientOriginalExtension() on the file to get the extension in Laravel.
VueJS
imagePreview(event) {
let selectedFile = event.target.files[0];
vm.image = selectedFile;
}
submitForm(){
let fomrData = new FormData();
formData.append('image', vm.image);
axios.post(this.$apiUrl + '/article', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
flash(response.data.message, 'success');
})
.catch(e => {
console.log(e);
});
}
Laravel
$this->validate($request, [
'image' => 'required',
]);
$image = $request->file('image');
$extension = $image->getClientOriginalExtension(); // Get the extension
$timestampName = microtime(true) . '.' . $extension;
$url = env('AWS_URL') . '/article_images/' .$timestampName;
Storage::disk('s3')->put($url, file_get_contents($image));
Here is a link that might be useful
Hope that it helps.
Related
I have an app developed using ionic angular and I want to upload files and send to laravel php
here I what I have done but this not working.
Here is my submit form in ionic angular :
async submitForm(){
let options = {headers: new HttpHeaders({
'Content-Type': 'multi-part/formdata',
}) };
let formData= new FormData();
formData.append("photo",this.file, this.file.name);
// console.log(formData)
this.http.post<any>(this.env.API_URL + 'auth/form', formData, options).subscribe(
data => {
this.alertService.presentToast("تم رفع الملفات بنجاح");
},
error => {
console.log(error);
},
)
laravel side:
public function apistore(Request $request)
{
$user = Auth::user()->id;
$this->validate($request, [
// 'photo' => 'required',
]);
$image = $request->{'photo'};
if($image->hasFile('photo'))
{
$file=$image->file('photo');
$filename = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$picture = date('His').'-'.$filename;
$file->move(public_path().'/attach/images', $picture);
}
$attachments= new attachments();
$attachments->filename=$image;
$attachments->user_id = Auth::user()->id;
$attachments->take_image = $request->{'take_image'};
$attachments->save();
return response()->json([
'success' => true,
'data' => $attachments->toArray(),
'message' => 'Data updated'
]);
}
I usually retrieve data from ionic like this and it is working
$job_info->job = $request->{'job_info.job'};
I have a problem, and I can't fix it. I read a lots of forum and issues, but it don't resolve.
The problem is that
$photos = $request->file('file');
return var_dump($photos);
bring NULL. I tried to find the error, but I can't
I want store images on server and in a table, then it connecting to an another products table,
First write in the inputs some data ex. Name,Category, after an other tab upload the images with Dropzone, and save it in one time together.
I am use rowanwins dropzone.
My ... .blade.php
<form method="POST" enctype="multipart/form-data" action="{{ route('product.createnew') }}">
// Other Products inputs ..
//Uploads
<vue-dropzone
ref="myVueDropzone"
id="dropzone"
:options="dropzoneOptions">
</vue-dropzone>
// / form and scripts section
<script>
var url = "{{ route('product.createnew') }}";
console.log(url);
var app = new Vue({
el: '#app',
data: function () {
return {
dropzoneOptions: {
url: url,
thumbnailWidth: 150,
maxFilesize: 2,
maxFiles: 2,
acceptedFiles: ".jpeg,.jpg,.png,.gif",
autoDiscover : true,
clickable : true,
uploadMultiple :true,
addRemoveLinks:true,
headers: {
"X-CSRF-TOKEN": document.head.querySelector("[name=csrf-token]").content
},
},
radioButton: '0',
}
},
methods: {
deleteDropFile(index) {
this.dropFiles.splice(index, 1)
},
}
});
My Create Controller
public function create(Request $request)
{
$validator = Validator::make($request->all(), [
//Other products input
'file' => 'nullable|mimes:jpeg,jpg,png,gif|max:2048',
]);
//$products = new Products
//$products->save();
$photos = $request->file('file');
return var_dump($photos);
if (!is_array($photos)) {
$photos = [$photos];
}
for ($i = 0; $i < count($photos); $i++) {
$photo = $photos[$i];
$savename = sha1(time() . '.' . $request->get('name'))."_$i";
$images = new ProductImages ([
'name' => $request->get('name'),
'post_id'=> $products->id,
'path'=> public_path('uploads') . '/' . $savename,
'main'=> 0,
]);
$images->save();
Image::make($photo)
->resize(250, null, function ($constraints) {
$constraints->aspectRatio();
})
->save(public_path('uploads'). '/' . $savename);
$photo->move(public_path('uploads'), $savename);
}
return redirect()->back();
}
My routes
Route::group(['prefix' => 'product'], function () {
Route::get('/create', 'ProductController#index')->name('product.create'); //View
Route::post('/createnew', 'ProductController#create')->name('product.createnew'); //Post
});
After all I found what is wrong.
It is the validation
'file' => 'nullable|mimes:jpeg,jpg,png,gif|max:2048',
throw the error.
Thanks
I want to send a docx file to the client in the response of a get request:
Here's the Laravel controller code:
public function file($id)
{
$dlink = resource_path('temp/' . $id . '.docx');
$headers = [
'Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
];
return response()->download($dlink, $id . '.docx', $headers);
}
VueJS code:
axios.get(`${location.protocol}//${location.host}/api/download/${response.data}`,
{ responseType: "arraybuffer" }
)
.then(response => {
this.downloadFile(response);
})
.catch(err => alert(err));
downloadFile(response) {
var newBlob = new Blob([response.body], {
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
const data = window.URL.createObjectURL(newBlob);
var link = document.createElement("a");
link.href = data;
link.download = "resume.docx";
link.click();
setTimeout(function() {
window.URL.revokeObjectURL(data);
}, 100);
}
It doesn't show any error. but downloads a corrupted 9bytes docx file.
changing response.body to response.data did the job.
I am trying to upload image but getting the error Uncaught (in promise) Error: Request failed with status code 404
Here is my code
<input type="file" id="file" class="form-control-file" v-on:change="onFileChange">
methods:{
goToLogin(){
this.upload();
},
onFileChange(e){
console.log('onFileChange');
let files = e.target.files || e.dataTransfer.files;
if(!files.length){
return;
}
this.createImage(files[0]);
},
createImage(file){
console.log('createImage');
let reader = new FileReader();
let vm = this;
reader.onload = (e) =>{
vm.image = e.target.result;
};
reader.readAsDataURL(file);
},
upload(){
console.log('upload image= '+this.image);
axios.post('/storage/images',{image: this.image}).then(response => {
console.log(response.data);
});
}
}
public function saveImage(Request $request){
$image = $request->file('image');
$filename = time() . '.' . $image->getClientOriginalExtension();
$path = public_path('images/' . $filename);
$user->image = $filename;
$user->save();
}
In upload method i am getting data in image but issue is within '/storage/images'. Can anybody please help me to fix it.
I'm using laravel 4.2 and currently I don't how to save a csv file into public\csv\ directory using AJAX. I'm still finding some answers. Maybe someone can help me with this.
Here's my code:
In blade view:
{{Form::open(['route' => 'file_upload', 'files' => true, 'id' => 'upload_form', 'method' => 'POST'])}}
{{Form::file('csv_upload', ['id' => 'uploaded_file', 'accept' => 'text/csv'])}}
{{Form::submit('submit', ['class' => 'btn btn-primary btn-xs', 'id' => 'upload'])}}
{{Form::close()}}
Javascript Ajax:
var ajax_ready = 1
var token = {{Session::get('_token')}}
if($.type(originalOptions.data) === 'string') {
options.data = originalOptions.data+"&_token="+token;
}else if($.type(originalOptions.data) === 'object') {
//Here I got a new error
}else{
options.data = $.param(($.extend(originalOptions.data, {'_token':mmad_token})));
}
options.url = originalOptions.url.slice(0,originalOptions.url.indexOf("?_token="));
if (ajax_ready!=1){
jqXHR.abort();
}
ajax_ready = 0;
});
$('form#upload_form').on('submit', function(e){
e.preventDefault();
var uploadFile = $('#uploaded_file');
var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
var file = $('input[name="csv_upload"]').val();
if($.inArray(ext, ["csv"]) === -1) {
alert("Please upload a .csv file!");
return false;
}
var csv = uploadFile[0].files;
var form = new FormData(this);
var csvFile = {lastModifed: csv[0].lastModified, fileName: csv[0].name, size: csv[0].size, fileType: csv[0].type};
$.post('{{ URL::route("file_upload") }}?_token={{Session::token()}}',{
data: form
}).done(function(response){
});
});
PHP:
public function upload_csv()
{
$inputs = Input::all();
$csvFile = $inputs['data']['fileName'];
$path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
$path2 = public_path('csv/');
if(is_dir($path2))
{
#move_uploaded_file($csvFile, $path2.$csvFile); //This line can't move the uploaded files in my desired directory
}
return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);
}
This code below does work when not using AJAX:
if(Input::hasFile('csv_upload'))
{
$file = Input::file('csv_upload');
$originalFilename = $file->getClientOriginalName();
$rules = ['csv_upload' => 'required|file:csv'];
$validate = Validator::make(['csv_upload' => $file], $rules);
if($validate->fails())
{
return json_encode(['error' => 1, 'description' => 'File must be in .csv format']);
}
$path = public_path('/csv/');
if(!file_exists($path))
{
mkdir($path);
}
}
Console.log of csv
You can not move file because when you submit form with ajax file is not being sent with ajax,For sending file you have to send file with FormData() javascript Object.
If you check in upload_csv controller by putting print_r($_FILES); you will get empty array.
So use FormData on client side for appending file, then try agian.
You aren't getting error beacuse you have used php Error Control Operators likes#move_uploaded_file($csvFile, $path2.$csvFile);.
if you need working example then tell me i will give it to you.
Code For Your Help:
1. In blade view:
<script type="text/javascript">
$('form#upload_form').on('submit', function(e){
e.preventDefault();
var uploadFile = $('#uploaded_file');
var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
var file = $('input[name="mmad_csv_upload"]').val();
if($.inArray(ext, ["csv"]) === -1) {
alert("Please upload a .csv file!");
return false;
}
var csv = uploadFile[0].files;
var formData = new FormData($(this)[0]);
formData.append('uploaded_file', $("#uploaded_file")[0].files[0]);
formData.append('lastModifed', csv[0].lastModified);
formData.append('fileName', csv[0].name);
console.log(formData);
$.ajax({
url: '{{ URL::route("file_upload") }}',
type: 'POST',
data: formData,
async: true,
cache: false,
contentType: false,
processData: false,
success: function (returndata) { //alert(returndata); return false;
}
});
});
</script>
2.Controller
public function file_upload(Request $request)
{
$inputs = Input::all();
$csvFile = $inputs['fileName'];
$path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
$path2 = public_path('/csv/');
if(is_dir($path2))
{
$success = $request->file('uploaded_file')->move($path2, $csvFile);
}
return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);
}
To move the uploaded file to a new location, you should use the move method. This method will move the file from its temporary upload location (as determined by your PHP configuration) to a more permanent destination of your choosing:
Input::file('fileName')->move($destinationPath, $fileName);
If you need additional validations, you can check it at http://laravel.com/docs/5.1/requests#files
Default AJAX POST does not support file uploads. Use jQuery Form to upload files successfully. Full documentation of file upload at http://malsup.com/jquery/form/#file-upload
Below my example of a recentlty build script... My Controller uploads the files to S3, but is easy to be implemented with local storage.
var progress = function(event, position, total, percent) {
$(".progress-bar").width(percent + '%');
$(".progress-bar").html(percent + '%');
if(percent > 50) {
$(".progress-bar").css('color','#fff');
}
if(percent == 100) {
setTimeout(function(){
$(".progress").html('<span class="processing-msg">Processing... Please be patient!</span>');
$(".processing-msg").fadeIn('slow');
}, 1000);
}
}
var success = function(data) {
var obj = $.parseJSON(data);
$("#"+obj.hidden, parent.document).val(obj.filename);
var src = 'https://s3.amazonaws.com/spincms'+obj.path+'thumb_'+obj.filename;
$("#uploaded-"+obj.hidden, parent.document).html('<img class="img-circle uploaded-img" src="' + src + '">');
$(".progress").html('<span class="processing-msg-next">File has been uploaded and processed. Do not forget to submit the form!</span>');
}
var options = {
target: '#output',
uploadProgress: progress,
success: success,
resetForm: true
};
$(document).on('click', "#upload-now", function(e) {
$(".progress").html('<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>');
if($("#upload-form input[type=file]")[0].files.length == 0) {
$(".progress").html('<span class="processing-msg-next">No file selected!</span>');
return false;
} else {
var name = $("#upload-form input[name='name']").val();
var token = $("#upload-form input[name='_token']").val();
var file_name = $("#upload-form input[type=file]")[0].files[0].name;
$("#upload-form").ajaxSubmit(options);
}
}
});
Since you are using jQuery you can use the form plugin as it will make things much more easier for you to work with for example , this is the jquery part that you will use :
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$('#upload_form').ajaxForm(function() {
alert("Your file has been uploaded, thanks");
});
});
and in your controller you can code it like :
pubilc function postUpload()
{
$success = false;
if(Request::ajax())
{
if(Input::hasFile('csv_upload'))
{
$file = Input::file('csv_upload');
if(!File::isDirectory(storage_path('csv'))) {
File::createDirectory(storage_path('csv'));
}
$file->move(storage_path('csv'), $file->getClientOriginalName());
// now your file is on app/storage/csv folder
$filePath = storage_path('csv/'.$file->getClientOriginalName());
$success = true;
}
}
return Response::json(['success'=>$success]);
}