Laravel 5.8 image upload - laravel

After creating a Laravel site with user login, I wanted to add file upload ability. I followed a simple tutorial but when it came to do php artisan migrate it didn’t work because Base table or view already exists so I created an images table manually in MySQL.
Finally, I navigated to my websites image upload page http://localhost/sites/mywebsite/public/image and attached an image. The error I got was The POST method is not supported for this route. Supported methods: GET, HEAD.
This is the line in my image.blade.php file:
<form action="{{ url('save') }}" method="post" accept-charset="utf-8" enctype="multipart/form-data">
Note; When I created an images table manually in MySQL I only added 'id' and 'image' columns and I wasn't 100% sure how to format them.
Any help very much appreciated.
Here's my ImageController
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Validator, Redirect, Response, File;
use App\Image;
class ImageController extends Controller
{
public function index()
{
return view('image');
}
public function save(Request $request)
{
request()->validate([
'image' => 'required',
'image.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
]);
if ($image = $request->file('image')) {
foreach ($image as $files) {
$destinationPath = 'public/image/'; // upload path
$profileImage = date('YmdHis') . "." . $files->getClientOriginalExtension();
$files->move($destinationPath, $profileImage);
$insert[]['image'] = "$profileImage";
}
}
$check = Image::insert($insert);
return Redirect::to("image")->withSuccess('Great! Image has been successfully uploaded.');
}
}
Image.blade.php
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Laravel 5.7 Multiple Image Upload Example - Tutsmake.com</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
<style>
.container {
padding: 10%;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h2 style="margin-left: -48px;">Laravel 5.7 Multiple Image Upload Example - Tutsmake.com</h2>
<br>
<br>
#if ($message = Session::get('success'))
<div class="alert alert-success alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
<br>
#endif
#if (count($errors) > 0)
<div class="alert alert-danger">
<strong>Opps!</strong> There were something went wrong with your input.
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
<br>
#endif
<form action="{{ url('save') }}" method="post" accept-charset="utf-8" enctype="multipart/form-data">
#csrf
<div class="avatar-upload col-6">
<div class=" form-group avatar-edit">
<input type='file' id="image" name="image[]" accept=".png, .jpg, .jpeg" />
<label for="imageUpload"></label>
</div>
</div>
<div class="form-group col-3">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</form>
</div>
</body>
</html>
Migration table
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateImagesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('images', function (Blueprint $table) {
$table->increments('id');
$table->increments('image');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('images');
}
}

Follow Any Method :
<form action="{{ url('save') }}" method="get" accept-charset="utf-8" enctype="multipart/form-data">
And Change Migartion $table->text('image');
OR
Route::post('save', 'ImageController#save');
And Change Migartion $table->text('image');

You need to create a POST method route in routes/web.php.
A get route does not support posting form data
Route::post('save', 'ImageController#save');
Also, the image column in your database should be a string, an integer can't hold a path to a file
$table->string('image');
But you can't insert an array to a string column anyway so you should move the Model create method inside the foreach loop
foreach ($image as $files) {
$destinationPath = 'public/image/'; // upload path
$profileImage = date('YmdHis') . "." . $files->getClientOriginalExtension();
$files->move($destinationPath, $profileImage);
Image::insert($profileImage);
}

Related

Laravel Multiple Image upload with other fields

I am new to Laravel and trying to add multiple record dynamically with images. If I keep only the image fields the records are getting saved to the database successfully but if I add other fields (subject) the record is not getting saved to database. Please help
UI and Error
Error Messages - Trying to access array offset on value of type null
UI and Error Image
The following is my Welcome.blade.php file
<!-- js -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta3/dist/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript">
var i = 0;
$("#dynamic-ar").click(function() {
++i;
$("#dynamicAddRemove").append('<tr><td><input type="text" name="addMoreInputFields[' + i +
'][studentname]" placeholder="Enter your Name" class="form-control" /></td><td><input type="text" name="addMoreInputFields[' +
i +
'][subject]" placeholder="Enter your subject" class="form-control" /></td><td><input type="file" id="image" name="addMoreInputFields[' +
i +
'][image]" placeholder="Enter your image" class="form-control" /></td><td><button type="button" class="btn btn-danger remove-input-field">Remove</button></td></tr>'
);
});
$(document).on('click', '.remove-input-field', function() {
$(this).parents('tr').remove();
});
</script>
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Add Multiple records</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>.container { max-width: 600px;}</style>
</head>
<body>
<div class="container">
<form action="{{ url('store-input-fields') }}" method="POST" enctype="multipart/form-data">
#csrf
#if ($errors->any())
<div class="alert alert-danger" role="alert">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
#if (Session::has('success'))
<div class="alert alert-success text-center">
<p>{{ Session::get('success') }}</p>
</div>
#endif
<table class="table table-bordered" id="dynamicAddRemove">
<tr>
<th>studentname</th>
<th>Subject</th>
<th>Image</th>
<th>Action</th>
</tr>
<tr>
<td><input type="text" name="addMoreInputFields[0][studentname]" placeholder="Enter studentname" class="form-control" /></td>
<td><input type="text" name="addMoreInputFields[0][subject]" placeholder="Enter subject" class="form-control" /></td>
<td><input type="file" name="addMoreInputFields[0][image]" placeholder="Enter image" class="form-control" /></td>
<td><button type="button" name="add" id="dynamic-ar" class="btn btn-outline-primary">Add More</button></td>
</tr>
</table>
<button type="submit" class="btn btn-outline-success btn-block">Save</button>
</form>
</div>
</body>
</html>
The controller file code
namespace App\Http\Controllers;
use App\Models\Student;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class StudentController extends Controller
{
public function index()
{
return view('welcome');
}
public function store(Request $request){$request->validate([
'addMoreInputFields.*.studentname' => 'required',
'addMoreInputFields.*.subject' => 'required',
'addMoreInputFields.*.image' =>
'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
foreach ($request->addMoreInputFields as $key => $value) {
if ($files = $request->file('addMoreInputFields.*.image')) {
$destinationPath = public_path('/images/'); // upload path
foreach ($files as $img) {
// Upload Image
$profileImage = uniqid() . '_' . date('d-m-Y') . '_' . microtime(true) . '_' . $img->getClientOriginalName();
try {
if (!Storage::exists('images/' . $profileImage)) {
$img->move($destinationPath, $profileImage);
}
} catch (\Exception$e) {
return $e->getMessage();
}
$imagemodel = new Student();
$imagemodel->image = "$profileImage";
//$imagemodel->subject = "$subject";
//$imagemodel -> subject = $request->input('addMoreInputFields.*.subject.'.$value);
$imagemodel->subject = $request->subject[$value];
$imagemodel->studentname = $destinationPath . $profileImage;
$imagemodel->save();
}
}
}
return back()->with('success', 'New reord has been added.');
}
}
The following is my model file code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
use HasFactory;
protected $fillable = [
'studentname',
'subject',
'image',
];
}
The migration file
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->string('studentname');
$table->string('subject');
$table->string('image')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('students');
}
};

How to upload image to Laravel storage?

I'm trying to implement this guide on how to upload an image to the laravel storage but when I submit, it shows that the page is expired. There is not error report in the log which makes it difficult to debug.
web.php:
Route::get('/upload-image', [StorageController::class, 'index']);
Route::post('/save', [StorageController::class, 'save']);
StorageController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Image;
use App\Models\Photo;
class StorageController extends Controller
{
public function index()
{
return view('image');
}
public function save(Request $request)
{
$validatedData = $request->validate([
'image' => 'required|image|mimes:jpg,png,jpeg,gif,svg|max:2048',
]);
$name = $request->file('image')->getClientOriginalName();
$path = $request->file('image')->store('public');
$save = new Photo;
$save->name = $name;
$save->path = $path;
$save->save();
return redirect('upload-image')->with('status', 'Image Has been uploaded');
}
}
Model Photo.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Photo extends Model
{
use HasFactory;
}
Laravel view to upload the image image.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Laravel 8 Uploading Image</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
#if(session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
#endif
<div class="card">
<div class="card-header text-center font-weight-bold">
<h2>Laravel 8 Upload Image Tutorial</h2>
</div>
<div class="card-body">
<form method="POST" enctype="multipart/form-data" id="upload-image" action="{{ url('/save') }}" >
<div class="row">
<div class="col-md-12">
<div class="form-group">
<input type="file" name="image" placeholder="Choose image" id="image">
#error('image')
<div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
#enderror
</div>
</div>
<div class="col-md-12">
<button type="submit" class="btn btn-primary" id="submit">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
So when I navigate to localhost/upload-image it shows the view and I can choose a file in the input form but as soon as I click on the submit button, the page navigates to /save and shows 419 | Page Expired with no log entry. The browser console shows:
POST http://127.0.0.1:8000/save 419 (unknown status)
You are not passing #csrf token in form request:
<form method="POST" enctype="multipart/form-data" id="upload-image" action="{{ url('/save') }}" >
#csrf
Please pass as per above code example then it will be work.
You should include #csrf in your form tags.
<form method="POST" enctype="multipart/form-data" id="upload-image" action="{{ url('/save') }}" >
#csrf
</form>

Laravel Backpack file upload

I recently installed laravel backpack
And my form has a pdf file to upload
I read the tutorial on backpack but was unable to solve it
I Debugged and found that
request()->hasFile() is empty
no file in request
and html code of the add form has no enctype="" in it
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\FileUploadController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('file-upload', [FileUploadController::class, 'fileUpload'])->name('file.upload');
Route::post('file-upload', [FileUploadController::class, 'fileUploadPost'])->name('file.upload.post');
Create FileUploadController
app/Http/Controllers/FileUploadController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class FileUploadController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function fileUpload()
{
return view('fileUpload');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function fileUploadPost(Request $request)
{
$request->validate([
'file' => 'required|mimes:pdf,xlx,csv|max:2048',
]);
$fileName = time().'.'.$request->file->extension();
$request->file->move(public_path('uploads'), $fileName);
return back()
->with('success','You have successfully upload file.')
->with('file',$fileName);
}
}
Create Blade File
resources/views/fileUpload.blade.php
<!DOCTYPE html>
<html>
<head>
<title>laravel 8 file upload example - ItSolutionStuff.com.com</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading"><h2>laravel 8 file upload example - ItSolutionStuff.com.com</h2></div>
<div class="panel-body">
#if ($message = Session::get('success'))
<div class="alert alert-success alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
#endif
#if (count($errors) > 0)
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<form action="{{ route('file.upload.post') }}" method="POST" enctype="multipart/form-data">
#csrf
<div class="row">
<div class="col-md-6">
<input type="file" name="file" class="form-control">
</div>
<div class="col-md-6">
<button type="submit" class="btn btn-success">Upload</button>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
Laravel Backpack is for admin CRUD functionalities. All you need to do in the admin controller is to define the field type as "Browse" for file upload. Example, below is to upload and file. It will upload single file in your laravel default filesystem and save the path in photo_path field of database.
$this->crud->addField([ // Photo
'name' => 'photo_path',
'label' => "Photo",
'type' => 'browse'], 'both');
This is for the admin only, if you want upload feature for frontend, Backpack API's are not for that. In that case, check in Laravel docs.

Laravel: Login system problem for learning

I'm trying to make a login for learning, so I followed a video from youtube with the same coding. It should be able to check the format of the inputted data, check whether user already login or not, check whether user accessing the next page wihthout login, but in the end, it will always only showed email and password required errors even if I already inputted the right input. Please help. Here are my codes.
web.php
<?php
use Illuminate\Support\Facades\Route;
Route::get('/main', 'MainController#index');
Route::post('/main/checklogin', 'MainController#checklogin');
Route::get('main/successlogin', 'MainController#successlogin');
Route::get('main/logout', 'MainController#logout');
login.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Login</title>
<!--CSS-->
<link rel="stylesheet" href="{{ asset('css/styles.css') }}" type="text/css">
<link rel="stylesheet" href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' />
<script type="text/javascript" src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'></script>
</head>
<body>
<div class="login-page-frame">
<div class="header-login-page-frame">
<h3>Login</h3>
</div>
<div class="inner-login-form-frame">
#if(isset(Auth::user()->email))
<script>window.location="/main/successlogin";</script>
#endif
#if($message = Session::get('error'))
<div class="alert alert-danger alert-block">
<button type="button" class="close" data-dismiss="alert"></button>
<strong>{{$message}}</strong>
</div>
#endif
#if(count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<form method="post" action="{{ url('/main/checklogin') }}" class="login-form">
{{ csrf_field() }}
<input type="email" placeholder="email" name="login-email" class="form-control">
<br>
<input type="password" placeholder="pass" name="login-password" class="form-control">
<br>
<input type="submit" name="login" class="btn-login" value="login">
</form>
</div>
</div>
</body>
</html>
halamanUtama.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Halaman Utama</title>
</head>
<body>
<div class="container box">
<h3 align="center">Selamat Datang</h3>
<br />
#if(isset(Auth::user()->email))
<div class="alert alert-danger success-block">
<strong>Welcome {{ Auth::user()->email }}</strong>
<br />
Logout
</div>
else
<script>window.location="/main";</script>
#endif
</div>
</body>
</html>
MainController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Validator;
use Auth;
use Input;
class MainController extends Controller
{
//
function index(){
return view('login');
}
function checklogin(Request $request){
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|alphaNum|min:3'
]);
$user_data=array(
'email' => $request->get('login-email'),
'password' => $request->get('login-password')
);
if(Auth::attempt($user_data)){
return redirect('main/successlogin');
}else{
return back()->with('error', 'Wrong Login Details');
}
}
function successlogin(){
return view('halamanUtama');
}
function logout(){
Auth::logout();
return redirect('main');
}
}
I won't comment on whether any of your other code works, but the cause of your validation errors is that the name of your form inputs does not match the name of the fields you are trying to validate.
In your form, your inputs are called login-email and login-password. However, in your controller, you are validating that a field called email and a field called password are provided (because they are required).
So either change your form names to email and password or change your validation fields to login-email and login-password.

Response is empty string

I am creating a simple upload files web application using laravel in the backend and I am trying to print the response that is sent from the server -which is supposed to be informed about the uploaded file- in the console, but it shows me an empty string.
here is my controller:
<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Storage;
class UploadsController extends Controller
{
public function getUpload(){
return view('upload');
}
public function postUpload(request $request){
// //
$result = print_r($request,true);
$time = Carbon::now();
if ($request->hasFile('file')) {
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$fileName = $file->getClientOriginalName();
//$upload_success = $file->storeAs('public',$file->getClientOriginalName());
$upload_success=Storage::disk('local')->put($fileName, fopen($file, 'r+'));
if ($upload_success) {
return response()->json(['request'=>$request->getContent()], 200);
}
else {
return response()->json('error', 400);
}
}
return response()->json('no file to upload', 400);
}
}
and my view where I am printing the response:
<html>
<head>
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>upload</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="/js/xhr2.js"></script>
<script type="text/javascript">
$(function(){
$('#upload').on("click",function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$("#file").upload("/upload",function(data){
$('#spin').css('display','none');
$('#msg').css('display','block');
console.log(data);
},function(prog,val){
$('#prog').html(val+"%");
$('#prog').width(''+val+'%');
if(val == 100){
$("#prog").html('Completed');
$('#spin').css('display','block');
}
});
});
});
</script>
</head>
<body>
<div class="container">
<div style="margin-top:5px"><input type="file" id="file" name="file" ></div>
<div style="margin-top:5px;margin-bottom: 5px">
<input type="button" id="upload" value="upload" class="btn btn-success btn-lg">
</div>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 0%;" aria-valuemin="0" aria-valuemax="100" id="prog"></div>
</div>
<div id="spin" style="display:none">
<i class="fa fa-circle-o-notch fa-spin" style="font-size:24px"></i>
</div>
<div class="alert alert-success" style="display: none" id="msg" style="text-align: center">
<strong>Success!</strong>You have uploaded the file successfully
</div>
</div>
</body>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</html>
and here is a sample of what I get:
I would know if I am doing it wrong, and if not, why it is empty,
Thanks.
You're not using a form element.
Wrap your inputs in a basic html form:
<form method="POST" action="#">
#csrf
...
</form>
Then use jquery to post the form to the laravel route.

Resources