Good evening, how to make a download feature (from another website link) in laravel 8?
for example I have a data link "download zip" from the github repository, then I want when I click download (in view) it will download from the github repo link.
actually it can be created in a view like <a href="$data->link">, but this method can't add the "download" value in the table.
I want to do this in the controller and when there is a download request it will also add value to the download field (table).
web.php
Route::get('source-code/download/{id}', [FrontController::class, 'download'])->name('download');
FrontController.php
public function download($id)
{
$sc = Sourcecode::findOrFail($id);
$sc->increment('download');
$sc->update();
if ($sc->file)
{
$file_path = public_path('storage/'.$sc->file);
return response()->download($file_path);
}
else
{
$headers = [
'Content-Type' => 'application/zip',
];
return response()->download($sc->link, 'testing.zip', $headers);
}
}
view
#if($sc->file || $sc->link)
<a href="{{ route('download', $sc->id) }}" target="_blank" rel="noopener" class="btn btn-primary btn-sm text-white">
Download
</a>
#endif
Currently, I can download from the folder, but from other website links, I still can't. how to make a feature like this? thank you
The method reponse()->download only seems to work on local files. If you want something similar for a remote file you can try the following:
public function download($id)
{
$sc = Sourcecode::findOrFail($id);
$sc->increment('download');
$sc->update();
if ($sc->file)
{
$file_path = public_path('storage/'.$sc->file);
return response()->download($file_path);
}
else
{
$data = file_get_contents($sc->link);
$headers = [
'Content-Type' => 'application/zip',
'Content-Disposition' => 'attachment; filename="testing.zip"',
'Content-Length' => strlen($data)
];
return response($data, 200, $headers);
}
}
Be aware that this will need to read the entire file in memory.
If the file is large then you can use a streamed download
Related
On my page I am making an invoice that is fully compatible with Livewire. I use this package: https://github.com/LaravelDaily/laravel-invoices to generate my invoice and everything works fine. But their is one problem I ran into. I can't download my PDF with Livewire.
Here is a basic example to generate a PDF and download it:
public function invoice()
{
$customer = new Buyer([
'name' => 'John Doe',
'custom_fields' => [
'email' => 'test#example.com',
],
]);
$item = (new InvoiceItem())->title('Service 1')->pricePerUnit(2);
$invoice = Invoice::make()
->buyer($customer)
->discountByPercent(10)
->taxRate(15)
->shipping(1.99)
->addItem($item);
return $invoice->download();
}
Whenever I click on a button
<a role="button" class="pdf-download cursor-pointer" wire:click="invoice">download</a>
Nothing happens. So the problem is that Livewire doesn't support this download method. And this download method looks like this:
public function download()
{
$this->render();
return new Response($this->output, Response::HTTP_OK, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="' . $this->filename . '"',
'Content-Length' => strlen($this->output),
]);
}
$this->render(); Renders a template in a specific folder
Is their a work around for this? Where I can download my pdf with a template or maybe a different strategy. I allready tried one thing. I stored the invoice into a session, like so:
Session::put('invoice', $invoice);
Session::save();
And in a different controller I have.
if ($invoice = Session::get('invoice')) {
$invoice->download();
}
But that gives me this error:
serialization of 'closure' is not allowed
And I tried some stuff I found here: https://github.com/livewire/livewire/issues/483
But nothing works. Can someone give me a direction on where to look or how to fix this? Thanks!
return response()->streamDownload(function () use($invoice) {
echo $invoice->stream();
}, 'invoice.pdf');
Seems to do the trick.
I want to make a private directory using Laravel 6.
Only users who have already logged in can access the directory.
So, I implemented below:
routes/web.php
Route::group(['middleware' => ['private_web']], function() { // 'private_web' includes auth
Route::get('/private/{path?}', 'PrivateController#index')->name('private')->where('path', '.*');
});
PrivateController.php
public function index(Request $request, $path = null) {
$storage_path = 'private/' . $path;
$mime_type = Storage::mimeType($storage_path);
$headers = [ 'Content-Type' => $mime_type, ];
return Storage::response($storage_path, null, $headers);
}
It is working.
But, when I got a html from the directory using Chrome, a css linked from the html wasn't applied (the css is in private directory and just downloaded successfully).
The cause is already known and it is Storage::mimeType returns 'text/plain' against css.
I can fix it by making a branch:
if (ends_with($path, '.css')) {
$mime_type = 'text/css';
} else {
$mime_type = Storage::mimeType($storage_path);
}
Question:
Is there more better solution?
I'm afraid of increasing such branch at each file type...
thanks.
I have Laravel project from Github, I am trying to export the selected column to a txt file. The table name is customers and the column name is customer_contact_numbers from the database khanoilsdb
Here is the error I am facing:
I have added a new controller and the following code to it:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class CNController extends Controller
{
$customers = Customer::all();
$phoneNumbers = "Phone numbers \n";
foreach ($customers as $customer) {
$content .= $customer->customer_contact_numbers;
$content .= "\n";
}
// file name to download
$fileName = "contact_numbers.txt";
// make a response, with the content, a 200 response code and the headers
return Response::make($content, 200, [
'Content-type' => 'text/plain',
'Content-Disposition' => sprintf('attachment; filename="%s"', $fileName),
'Content-Length' => sizeof($content)
];);
}
Web.php:
Route::get('/home', 'CNController');
And the button:
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item" href="{{ route('CNController') }}">Export</a>
</div>
What I am trying to do is, after users click on it, it will call the controller method and start downloading a txt file.
Sorry if I'm not able to explain properly, I'm new to Laravel and PHP. Thanks :)
The problem is that you don't have a function in your class.
You can add a new function exportNumbers like this:
class CNController {
public function exportNumbers() {
// Your code here
}
}
Then you have to edit the web.php file to call this function:
Route::get('/home', 'CNController#exportNumbers');
I want to load pdf file in html but i got an error.
here is my function
public function getDocument($file){
$filePath = 'app/final/attachments/AA-19-4-2019-18123/'.$file;
$type = Storage::mimeType($filePath);
$pdfContent = Storage::get($filePath);
return Response::make($pdfContent, 200, [
'Content-Type' => $type,
'Content-Disposition' => 'inline; filename="'.$file.'"'
]);
}
here is my route
Route::get('/documents/pdf-document/{file}', 'inboxController#getDocument');
and here is my code in blade
<embed src="{{ action('inboxController#getDocument', ['file'=> basename($attach)]) }}" style="width:100%;height:auto;overflow: hidden;" frameborder="0" allowfullscreen>
it seems like, the error is because of the filename of the file. When i changed it to asdf.pdf, it loaded the file, but when i change its filename i wont loaded anymore. Images doesnt have really a problem. only pdf files. Please help me
edit
when i tried to use this static code, then remove {file} from route and also in blade, then pdf will loaded. i cant figure it out why.
public function getDocument(){
$filePath = 'app/final/attachments/AA-19-4-2019-18123/my.pdf';
$type = Storage::mimeType($filePath);
$pdfContent = Storage::get($filePath);
return Response::make($pdfContent, 200, [
'Content-Type' => $type,
'Content-Disposition' => 'inline; filename="'.$file.'"'
]);
}
You can do it this way :
php artisan storage:link
Next Go to the storage folder under 'public', and create a Folder 'FOLDER_NAME'
Your function :
public function getDocument($filename){
return response()->file('storage/FOLDER_NAME/'.$filename);
}
In your routes, web.php :
Route::get('/pdf/{filename}', ['as' => 'filename', 'uses' => 'ControllerName#getDocument' ]);
Then you can call it from your blade :
See PDF File:
I have a Laravel 5.5 app where users with administrator privileges can upload files. After they upload the files I'd like them to be able to view the file in the administrator dashboard.
I have a DocumentController.php that handles the file upload to the local disk:
public function store(Request $request)
{
// check to make sure user is an admin
$request->user()->authorizeRoles('admin');
// validate that the document is a pdf and
// that required fields are filled out
$this->validate($request, [
'title' => 'required',
'description' => 'required',
'user_id' => 'required|exists:users,id',
'document_path' => 'required|mimes:pdf'
]);
$file = $request->file('document_path');
$path = $file->store('documents/' . $request->user_id);
$document = Document::create([
'user_id' => $request->user_id,
'title' => $request->title,
'description' => $request->description,
'file_path' => $path
]);
return redirect($document->path());
}
This method takes the file from the form, makes sure it is a pdf and then saves the file to storage/app/documents/{user_id}. It then creates a Document record in the database and forwards to the URL based on the document id: /admin/document/{ $document->id }
That route is defined as Route::get('/admin/document/{document}', 'DocumentController#show');
Where in the controller I pass the document to the view:
public function show(Document $document, Request $request)
{
// check to make sure user is an admin
$request->user()->authorizeRoles('admin');
$storagePath = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix();
return view('admin.document', compact('document', 'storagePath'));
}
On that page I would like to display the pdf document.
resources/views/admin/document.blade.php
#extends('layouts.app')
#section('content')
<div class='container'>
<div class='row'>
<div class='col-sm-2'>
<a href='/admin'>< Back to admin</a>
</div>
<div class='col-sm-8'>
{{ $document }}
<embed src="{{ Storage::url($document->file_path) }}" style="width:600px; height:800px;" frameborder="0">
</div>
</div>
</div>
#endsection
I have tried using the $storagePath variable and Storage methods but cannot get the pdf file to display within the iframe.
Using local file storage how would I display the file in the browser? Also, I've protected the route so that only admins can view the document's page but what is the best way to secure the path to the document itself?
If you want your files to be protected (only admin can access them), then you need to create a new route and new DocumentController method getDocument
Add new route
Route::get('documents/pdf-document/{id}', 'DocumentController#getDocument');
In DocumentController, add
use Storage;
use Response;
Add new method that will read your pdf file from the storage and return it back
public function getDocument($id)
{
$document = Document::findOrFail($id);
$filePath = $document->file_path;
// file not found
if( ! Storage::exists($filePath) ) {
abort(404);
}
$pdfContent = Storage::get($filePath);
// for pdf, it will be 'application/pdf'
$type = Storage::mimeType($filePath);
$fileName = Storage::name($filePath);
return Response::make($pdfContent, 200, [
'Content-Type' => $type,
'Content-Disposition' => 'inline; filename="'.$fileName.'"'
]);
}
In your view you can show the document like this
<embed
src="{{ action('DocumentController#getDocument', ['id'=> $document->id]) }}"
style="width:600px; height:800px;"
frameborder="0"
>
Shorter version of that Response::make() from #ljubadr answer:
return Storage::response($document->file_path)
<embed
src="{{ url('/filepath') }}"
style="width:600px; height:800px;"
frameborder="0">