Cannot read PDF converted back from BLOB in Laravel 5? - php

I am trying to save files in the DB using BLOB. I know it is not a very good practice but it needs to be done this way.
Anyway the problem that I am facing is that PDF files returned are not readable anymore. But all other files like docx, odt, txt, jpg and so on are working just fine when converted back from blob.
public function store(Request $request)
{
$data = $request->all();
$file = $request->file('file');
$data['data'] = base64_encode(file_get_contents($file));
$data['extension'] = $file->guessExtension();
$data['name'] = $file->getClientOriginalName();
$file = $this->fileRepo->create($data);
return jsend()->success()
->message("Resource Created Successfully")
->data($file->toArray())
->get();
}
public function download($id)
{
$file = $this->fileRepo->find($id);
$randomDir = md5(time() . $file->id . $file->user->id . str_random());
mkdir(public_path() . '/files/' . $randomDir);
$path = public_path() . '/files/' . $randomDir . '/' . html_entity_decode($file->name);
file_put_contents($path, base64_decode($file->data));
header('Content-Description: File Transfer');
return response()->download($path);
}
Where am I going wrong and is there a special way to store the PDFs in a blob field?

It's possible that the headers are being returned incorrectly and this is causing the file to appear unreadable.
Force them by replacing:
header('Content-Description: File Transfer');
return response()->download($path);
With:
$headers = array(
'Content-Description: File Transfer',
'Content-Type: application/octet-stream',
'Content-Disposition: attachment; filename="' . $file->name . '"',
);
return response()->download($path, $file->name, $headers);

You can set your header return like that. you need to use Laravel's response ie.
public function download($id)
{
$file = $this->fileRepo->find($id);
$randomDir = md5(time() . $file->id . $file->user->id . str_random());
mkdir(public_path() . '/files/' . $randomDir);
$path = public_path() . '/files/' . $randomDir . '/' . html_entity_decode($file->name);
file_put_contents($path, base64_decode($file->data));
return response()->download($path)->header('Content-Description', 'File Transfer');
}

Related

Can i display/open/preview base64 pdf without store in Laravel

Currently I am storing file into storage folder then show that file into browser and when close that file then remove that file from storage but I want directly show into browser and also can be download without store. This is working but storing file.
$fileFromAPI = $apiResponse->file;
$bin = base64_decode($fileFromAPI, true);
$path = config('pdf_paths.file') . $id . "/";
if (!is_dir($path)) {
$oldmask = umask(0);
Storage::makeDirectory($path, 0777, true);
umask($oldmask);
}
Storage::put($path . 'file_' . $fid . '.pdf', $bin);
$pdfread = 'storage/' . $path . 'file_' . $fid . '.pdf';
return response()->file($pdfread)->deleteFileAfterSend(true);
I found solution just set header and return it.
$fileFromAPI = $apiResponse->file;
$bin = base64_decode($fileFromAPI, true);
return response($bin)
->header('Content-Type', 'application/pdf');

Intervention image fail to update in Laravel

My problem is that all fields are updated, except the image field.
This is my Controller to update the form:
public function update(Meretrice $meretrice, MeretriceRequest $request)
{
if ($request->hasFile('avatar')) {
$meretrice->avatar = $request->file('avatar');
$filename = $meretrice->avatar->getClientOriginalName();
$save_path = storage_path('app/public') . '/meretrices/id/' . $meretrice->id . '/uploads/images/';
$path = $save_path . $filename;
$public_path = '/images/meretrice/' . $meretrice->id . '/avatar/' . $filename;
File::makeDirectory($save_path, $mode = 0755, true, true);
Image::make($meretrice->avatar)->save($save_path . $filename);
$meretrice->avatar = $public_path;
$meretrice->tags()->sync($request->tags);
$meretrice->update($request->validated());
}
return redirect()->route('meretrice.show', $meretrice)->with('info', 'successfully');
}
I use the same code to create and it creates successfully, but to edit I have the problem that not only the image field is updated

move 'tmp' directory not working when uploading image in laravel 5.4

When uploading my image it is saved to D:\xampp\tmp\phpD0E0.tmp directory. But I want to save it in public/uploads/banner. Anyone please help me. Here is my code:
BannersController.php
public function store(Request $request)
{
$requestData = $request->all();
if ($request->hasFile('banner_image')) {
foreach($request['banner_image'] as $file){
$uploadPath = public_path('/uploads/banner');
$extension = $file->getClientOriginalExtension();
$fileName = rand(11111, 99999) . '.' . $extension;
$file->move($uploadPath, $fileName);
$requestData['banner_image'] = $fileName;
}
}
Banner::create($requestData);
Session::flash('flash_message', 'Banner added!');
return redirect('Banner/banners');
}
Can you please revert that path to 'root' => storage_path('app/public')
and just try with change line:
$extension = $file->getClientOriginalExtension();
$fileName = rand(11111, 99999) . '.' . $extension;
with this:
$fileName = rand(11111, 99999) . '.' . $file->getClientOriginalName();
Hope this helps you.

After downloading file, it is corrupted

I'm currently making a controller to download files from the server.
It all happens in the index action:
public function indexAction() {
$schuurName = $this->_getParam('storageID');
$fileName = $this->_getParam('fileName');
$name = explode('.', $fileName)[0];
$path = '..' . DIRECTORY_SEPARATOR . 'schuren' . DIRECTORY_SEPARATOR . $schuurName . DIRECTORY_SEPARATOR . $fileName;
if (file_exists($path)) {
$mimeType = mime_content_type($fileName);
header('Content-Type: ' . $mimeType);
header('Content-Length: ' . filesize($path));
header('Content-Disposition: attachment; filename=' . $name . ';');
$resource = fopen($path, 'r');
while (!feof($resource)) {
$chunk = fread($resource, 4096);
echo $chunk;
}
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
}
else {
echo 'file doesn\'t exist';
}
}
So the downloading works right now, I'm testing it with an image of 725 bytes. The problem is.. The image is corrupted so it couldn't be seen/edited. What am I doing wrong in my code?
Thanks!
You should use binary mode. Use the 'rb' flag.
From the php Manual : If you do not specify the 'b' flag when working with binary files, you may experience strange problems with your data, including broken image files and strange problems with \r\n characters.
http://www.php.net/manual/en/function.fopen.php

Serving documents outside the web root folder.

I have a function called "viewDoc" which is supposed to go to a folder outside the web root and fetch a file for me. It seams to work ok with images (Jpgs etc) but with PDF's it just outputs a blank gray page as demonstrated here - http://www.tutorplanner.com/userimage/viewdoc/12787622467.pdf
Can anyone see what I'm doing wrong as I've been scratching my head over this for a day!
public function viewDoc($doc) {
$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$file = $doc;
$fileDir = '/var/uploads/';
if (file_exists($fileDir . $file))
{
$contents = file_get_contents($fileDir . $file);
//print_r($contents);
header('Content-Type: ' . mime_content_type($fileDir . $file));
header('Content-Length: ' . filesize($fileDir . $file));
readfile($contents);
}
}
readfile is used with the parameter of a file name - NOT text.
Two examples that would work (file_get_contents):
public function viewDoc($doc) {
$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$file = $doc;
$fileDir = '/var/uploads/';
$filePath = $fileDir . $file;
if (file_exists($filePath))
{
$contents = file_get_contents($filePath);
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Length: ' . filesize($filePath));
echo $contents;
}
}
or (readfile):
public function viewDoc($doc) {
$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$file = $doc;
$fileDir = '/var/uploads/';
$filePath = $fileDir . $file;
if (file_exists($filePath))
{
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
}
}
I also added the $filePath variable for you, as there's no reason to concat the string multiple times.
Edit
As extra security, to Yazmat's comment, you can use $file = str_replace(array('..', '/'), '', $doc); as this would remove all references to other directories (however, with the slash it would also remove access to sub directories, so you might want to skip that, dependend on your code and file structure).
You have a great security issue here, anyone can access anything on your server with the function you wrote. I realy advise you to not use it and just put your files (that should be accessible) on a public web directory.

Categories