Laravel count unique database value - laravel

I need to perform counting functionality:
The User can download only 5 files (total) per 24 hours. For example: User has 5 available downloads today, User downloaded myFile1.txt file and now he has 4 available downloads today, but if he wants to download myFile1.txt file again, he can do it as many times as he wants (still 4 available downloads), but if he downloaded new file myFile2.txt, now he has 3 available downloads.
My question, how to track, how many times a User downloaded a file.
This is my code:
/*
* $id {string} = file name;
* $dayStart (Timestamp) = example: 2020-03-25 00:00:00;
* $dayEnd (Timestamp) = example: 2020-03-26 00:00:00;
* $total (int) = how much User has downloaded;
* $response = file download functionality.
* auth()->user()->dailyDownloads (int) = default value 5.
*/
public function downloadFile(Request $request, $id){
$file = storage_path('app/files/') . $id .'.bin';
// Tracking operation date, find all records in this date interval.
$dayStart = Carbon::today();
$dayEnd = Carbon::tomorrow();
$total = DumpDownloadHistory::distinct('dataset')->where('user_id', auth()->user()->id)->
whereBetween('created_at', [$dayStart, $dayEnd])->count();
$findIfDownloaded = DumpDownloadHistory::distinct('dataset')->where('user_id', auth()->user()->id)->where('dataset', $id)->count();
if ($total >= auth()->user()->dailyDownloads) {
dd('To many downloads');
}
if (file_exists($file)) {
$headers = [
'Content-Type' => 'application/bin'
];
$response = response()->download($file, $id.'.bin', $headers, 'inline');
if ($response) {
// Storing download history to Database
auth()->user()->downloadHistorys()->create([
'user_id' => auth()->user()->id,
'dataset' => $id,
'user_ip'=> request()->ip()
]);
return $response;
}
} else {
abort(404, 'File not found!');
}
}

Related

How to queue upload to s3 using Laravel?

I'm dispatching a job to queue my video file, the files are being stored on s3.
Everything is working except if I upload a video file for example that's 20mb, when I look in my bucket it says the file is 120b. So this makes me think that I'm uploading the path and filename as a string instead of the file object.
And for some reason, when I try getting the file using the Storage::get() or File::get() and dd the result, it shows a bunch or random and crazy characters.
It seems like I can only get these weird characters, or a string, I can't get the file object for some reason.
In my controller I'm also storing it in the public disk (I will delete the file later in my Jobs/UploadVideos.php file).
CandidateProfileController.php:
$candidateProfile = new CandidateProfile();
$candidateProfile->disk = config('site.upload_disk');
// Video One
if($file = $request->file('video_one')) {
$file_path = $file->getPathname();
$name = time() . $file->getClientOriginalName();
$name = preg_replace('/\s+/', '-', $name);
$file->storePubliclyAs('videos', $name, 'public');
$candidateProfile->video_one = $name;
}
if($candidateProfile->save()) {
// dispatch a job to handle the image manipulation
$this->dispatch(new UploadVideos($candidateProfile));
return response()->json($candidateProfile, 200);
} else {
return response()->json([
'message' => 'Some error occurred, please try again.',
'status' => 500
], 500);
}
Jobs/UploadVideos.php:
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $candidateprofile;
public $timeout = 120;
public $tries = 5;
/**
* Create a new job instance.
*
* #param CandidateProfile $candidateProfile
*/
public function __construct(CandidateProfile $candidateProfile)
{
$this->candidateprofile = $candidateProfile;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$disk = $this->candidateprofile->disk;
$filename = $this->candidateprofile->video_one;
$original_file = storage_path() . '/videos/' . $filename;
try {
// Video One
Storage::disk($disk)
->put('videos/'.$filename, $original_file, 'public');
// Update the database record with successful flag
$this->candidateprofile->update([
'upload_successful' => true
]);
} catch(\Exception $e){
Log::error($e->getMessage());
}
}
File Storage docs
The 2nd parameter for put() should be the contents of the file not the path to the file. Also, unless you've updated the public disk in your config/filesystem.php, the video isn't going to be stored in storage_path() . '/videos/...'.
To get this to work you should just need to update your Job code:
$filename = 'videos/' . $this->candidateprofile->video_one;
Storage::disk($this->candidateprofile->disk)
->put($filename, Storage::disk('public')->get($filename), 'public');
$this->candidateprofile->update([
'upload_successful' => true,
]);
Also, wrapping your code in a try/catch will mean that the Job won't retry as it will technically never fail.

Laravel 5.4 file uploading error - fileName not uploaded due to an unknown error

Im trying to upload multiple images to via below code in laravel. In my form there are 3 types of images to be selected to upload. When user select all the images and then submit the form. I need to upload all the images to same folder . First images get uploaded in to the folder. But then it gives me below error.
The file "1575738164-main-slider2.webp" was not uploaded due to an unknown error.
Controller
if ($request->hasFile('image') && $request->hasFile('image_575') && $request->hasFile('image_768')){
$file = $request->image;
$file_575 = $request->image_575;
$file_768 = $request->image_768;
$name = time().'-'.$file->getClientOriginalName();
$name_575 = time().'-'.$file_575->getClientOriginalName();
$name_768 = time().'-'.$file_768->getClientOriginalName();
$names = [ $name , $name_575 , $name_768];
foreach ( $names as $n){
$file->move('uploads/banners/',$n);
}
$banner = new Banner();
$banner->name = $name;
$banner->name_575 = $name_575;
$banner->name_768 = $name_768;
$banner -> side_color = $request -> side_color ;
$banner->type = $request->type;
$banner->save();
}
Please note that I have almost gone through below questions.
Laravel: The file was not uploaded due to an unknown error
First only using time() method won't work to generate unique file name for all three images all the time and when a concurrent request occurs.
Second:
$names = [ $name , $name_575 , $name_768];
foreach ( $names as $n){
$file->move('uploads/banners/',$n);
}
What you are looping is totally wrong. You are trying to move the same image, $file for three times.
You have to move all the three images inside the loop:
`
$file = $request->image;
$file_575 = $request->image_575;
$file_768 = $request->image_768;
`
So, you should probably do:
$filesToMoves = [$name=> $file, $name_575 => $file2 , $name_768 => $file3];
foreach($filesToMoves as $fileName => $fileToMove){
$fileToMove->move('uploads/banners/',$fileName);
}
I will add my code for future references that I used to solve this issue
public function store(Request $request)
{
$this -> validate ( request () , [
'image' => 'required|mimes:webp|dimensions:max_width=1200,max_height=380|max:50' ,
'image_575' => 'required|mimes:jpeg,png,jpg|dimensions:max_width=575,max_height=380|max:80' ,
'image_768' => 'required|mimes:jpeg,png,jpg|dimensions:max_width=768,max_height=380|max:80' ,
] ) ;
if ($request->hasFile('image') && $request->hasFile('image_575') && $request->hasFile('image_768')){
$fils = [$request->image, $request->image_575, $request->image_768];
$formats = ['webp' , '575','768'];
$fileNames = [];
$i = 0;
foreach($fils as $file){
$name = time().'_'.$formats[$i].'.'.$file->getClientOriginalExtension();
$file->move('uploads/banners/', $name);
array_push($fileNames, $name);
$i++;
}
$a= new X();
$a->name = $fileNames[0];
$a->image_575 = $fileNames[1];
$a->image_768 = $fileNames[2];
$a->save();
}
This is just for information.

How to upload an image using Laravel?

The problem:
I want to upload an image to a mySQL database using Laravel.
what I have tried:
I looked for other stack-overflow questions but they weren't helpful.
the result I am expecting :
is to have the image name or path saved to a column in my table on the database , to retrieve and display it later as a post in a blog.
First you need the form on your view (don't forget the csrf token):
<form action="/image-upload" method="POST" enctype="multipart/form-data">
#csrf
<input type="file" name="image">
<button type="submit">Upload</button>
</form>
And on your routes file add the route for POST method:
Route::post('image-upload', 'ImageUploadController#imageUploadPost');
Then on your Controller create the function that will validate and move your image to the 'public/images' folder.
public function imageUploadPost()
{
request()->validate([
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$imageName = time().'.'.request()->image->getClientOriginalExtension();
request()->image->move(public_path('images'), $imageName);
}
For better solution please read this: Laravel File Storage
Actually with Laravel it only involves a few lines of code. Let's say you have a user that has an avatar which is stored in the database. Here's how you would store and retrieve the avatar from the database:
1. First you'll need to have an avatar column in the users table that can store binary data. Depending on how large you want to allow the avatar image to be, the data type of the column can be one of the following:
BLOB up to 64KB
MEDIUMBLOB up to 16MB
LONGBLOB up to 4GB
2. To store the uploaded image in the database you can do this:
Route::post('user/{id}', function (Request $request, $id) {
// Get the file from the request
$file = $request->file('image');
// Get the contents of the file
$contents = $file->openFile()->fread($file->getSize());
// Store the contents to the database
$user = App\User::find($id);
$user->avatar = $contents;
$user->save();
});
3. To fetch and ouput the avatar you can do the following:
Route::get('user/{id}/avatar', function ($id) {
// Find the user
$user = App\User::find(1);
// Return the image in the response with the correct MIME type
return response()->make($user->avatar, 200, array(
'Content-Type' => (new finfo(FILEINFO_MIME))->buffer($user->avatar)
));
});
NOTE: Please have this in your mind, MySQL isn't a suitable solution to store BLOB. You may need to use an object storage service like Amazon S3.
Use this to upload image
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// $this->validate($request,[//'movie_name'=>'required',
// // 'description'=>'required',
// //'video_url'=>'required',
// 'image'=>'required|mimes:jpeg,jpg,png,gif|required|max:10000',
// ]);
if ($request->hasFile('image') && $request->hasFile('image2')) {
$file = $request->file('image');
//$image=$file->getClientOriginalName();
$image = time().'.'.$file->getClientOriginalExtension();
$destinationPath ='assets/admin/uploads/image/';
$file->move($destinationPath,$image);
//echo $destinationPath;exit();
//echo $image."<br/>";
$file2 = $request->file('image2');
$bg_images = time().'.'.$file2->getClientOriginalExtension();
//$bg_images=$file2->getClientOriginalName();
$destinationPath ='assets/admin/uploads/bg_images/';
$file2->move($destinationPath,$bg_images);
$insert_data=array('movie_name'=>$request->movie_name,
'description'=>$request->description,
'video_url'=>$request->video_url,
'image'=>$image,
'bg_images'=>$bg_images,
'created_at'=>now(),
'updated_at'=>now()
);
//print_r($insert_data);exit();
}
else
{
if ( $request->hasFile('image2')) {
$file2 = $request->file('image2');
$bg_images = time().'.'.$file2->getClientOriginalExtension();
//$bg_images=$file2->getClientOriginalName();
$destinationPath ='assets/admin/uploads/bg_images/';
$file2->move($destinationPath,$bg_images);
//echo $destinationPath;exit();
//echo $bg_images;
$insert_data=array('movie_name'=>$request->movie_name,
'description'=>$request->description,
'video_url'=>$request->video_url,
//'image'=>$image,
'bg_images'=>$bg_images,
'created_at'=>now(),
'updated_at'=>now()
);
//print_r($insert_data);exit();
}
if ($request->hasFile('image') ) {
$file = $request->file('image');
//$image=$file->getClientOriginalName();
$image = time().'.'.$file->getClientOriginalExtension();
$destinationPath ='assets/admin/uploads/image/';
$file->move($destinationPath,$image);
//echo $destinationPath;exit();
//echo $image."<br/>";
$insert_data=array('movie_name'=>$request->movie_name,
'description'=>$request->description,
'video_url'=>$request->video_url,
'image'=>$image,
//'bg_images'=>$bg_images,
'created_at'=>now(),
'updated_at'=>now()
);
// print_r($insert_data);exit();
}
if ( ! $request->hasFile('image2') && ! $request->hasFile('image') ) {
$insert_data=array('movie_name'=>$request->movie_name,
'description'=>$request->description,
'video_url'=>$request->video_url,
//'image'=>$image,
// 'bg_images'=>$bg_images,
'updated_at'=>now()
);
// print_r($update_data);exit();
}
}
//exit();
// echo $image;
//exit();
//print_r($insert_data);exit();
$insert=DB::table('movies')->insert($insert_data);
if ($insert) {
return redirect()->route('admin.list_movies')->withSuccess('Record saved');
}
else {
return redirect()->route('admin.list_movies')->withError('Record not saved');
}
}

Laravel API can't update Microsoft Dynamic Nav Customer

I have a Laravel API hitting a MS Nav instance to carry out some data shuffling and migration between two systems. I am able to create Customer records in Nav just fine, but am running into some issues with updating.
I am able to perform a single PATCH request to update a customer record by any subsequent requests return the following error message.
{
"odata.error":{
"code":"",
"message":{
"lang":"en-US",
"value":"Another user has already changed the record."
}
}
}
Here's what my PHP code looks like if that makes a difference.
/**
* #param string $navNo
* #param string $eTag
* #param array $data
* #return array
*/
public function updateCustomer($navNo = '', $eTag = '', $data = []) {
$url = $this->config['uri'] . ':' . $this->config['port'] . '/' . $this->config['server'] . '/' . $this->config['service'] . '/CustomerCardPage';
$url .= "('$navNo')" . '?$format=json&company=' . $this->config['company'];
$options = [
'auth' => $this->config['auth'],
'headers' => [
'Content-Type' => 'application/json',
'If-Match' => 'W/"\'' . $eTag . '\'"',
],
'json' => $data,
];
return $this->makeRequest('PATCH', $url, $options);
}
/**
* #param $method
* #param $url
* #param $options
* #return array
*/
private function makeRequest($method, $url , $options) {
$response = ['success' => true, 'data' => null, 'error' => null];
try {
$res = $this->client->request($method, $url, $options);
$body = json_decode($res->getBody(), true);
$response['data'] = $body;
} catch (BadResponseException $e) {
$res = $e->getResponse()->getBody()->getContents();
$response['success'] = false;
$response['error'] = $res;
}
return $response;
}
I haven't been able to dig up anything helpful in the Nav support forums. Has anyone else run into this type of issue with Laravel/PHP or any other back-end language/framework?
Disclaimer: I have absolutely 0 experience with MS Dynamic Nav, nor do I have direct access to the Nav dashboard or whatever you would call it.
Here are the versions of the relevant framework/packages/services I am working with:
Laravel: 5.6
Guzzle: 6.3
Nginx: 1.13.6
Nav: ...? Can bug someone to find out if this would help.
Figured it out. The ETag is updated each time the customer updates since it acts as a version control. The error was basically telling me that I can't update the version because it was already updated previously.
To fix, just make sure to update the customer ETag after updating.

laravel retrieve json and save into database

I am getting cinema title + times using API from Cinelist, I then want to save these values into a database.
At the moment, it does save but only 1 record, the last one. However, I want it to save each one.
Also each time it is run I want to update existing records instead of creating new ones unless there are more results.
So usually there are 5 records, each time I run the function I want to update the database with the new 5 records, however, if it's a different day and there are 6 records I want to update 5 records and insert 1 extra one so there is 6.
My code so far:
function odeon(){
$data= file_get_contents('https://api.cinelist.co.uk/get/times/cinema/10565');
$data = json_decode($data);
foreach($data->listings as $listing){
$title = $listing->title;
$time = implode(', ', $listing->times);
$id = + 1;
$films = Film::where('id', $id)->first();
if (!$films) {
$films = new Film();
}
$films->title = $title;
$films->times = $time;
$films->save();
}
}
You may use eloquent's updateOrCreate method to insert non-existent data and update existing data.
function odeon(){
$data= file_get_contents('https://api.cinelist.co.uk/get/times/cinema/10565');
$data = json_decode($data);
foreach($data->listings as $listing){
$title = $listing->title;
$time = implode(', ', $listing->times);
Films::updateOrCreate([
'title' => $title,
'$times' => $time
]);
}
}

Resources