Display/Download a file from server using Symfony2 and jQuery - php

Using Symfony2.0 and jQuery
My application generates and stores PDF outside the ./www folder as it is private information (comercial invoices for the purchases within my shop).
I am trying and not getting to allow the customer to download their invoices at any time.
I found this article, but at the beginning it talks about how to get them from the "public" ./www folder. At the end, it offers a piece of code, but I think it is not supported by my version of Symfony:
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class OfflineToolController extends Controller
{
/**
* #return BinaryFileResponse
*/
public function downloadAction()
{
$path = $this->get('kernel')->getRootDir(). "/../downloads/";
$file = $path.'my_file.zip'; // Path to the file on the server
$response = new BinaryFileResponse($file);
// Give the file a name:
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT,'my_file_name.zip');
return $response;
}
}
This is the case: How to create a link to download generated documents in symfony2?
Any idea of how to do this?

Related

How to import and register class from a list of service providers at runtime?

Are you able to solve this problem? help me
Procedure
There is a folder called 'plugins' in the base path of laravel;
Inside that folder there are only subfolders that are the plugins;
In the subfolder where the plugin is, there is a single file to be imported called PluginNameServiceProvider.php;
The PluginNameServiceProvider.php in turn will be registered by a main service provider, let's say MainServiceProvider.php, but for that, the PluginNameServiceProvider class must be available/accessible for use;
Problem
The user loads the subfolder containing the 'plugin' in 'zip' format through a GUI, then the system extracts the loaded 'zip' file and directs it to the appropriate location, no similar file exists before that;
When the 'composer update or composer dump-autoload' command is executed the PluginNameServiceProvider class is resolved and can be used elsewhere, but not before that;
The aforementioned composer commands are executed at fixed times, however, the PluginNameServiceProvider class must be available immediately, not being able to depend on composer under penalty of preventing the use of the plugin;
What was tried
A temporary autoloader was created that searches for classes not yet resolved by composer as below, however, it is not working
try{
/**
* For information on 'spl_autoload_register' see: https://www.php.net/manual/en/function.spl-autoload-register.php
* For information on 'glob()' see: https://www.php.net/manual/en/function.glob.php
* For information on 'app()' see: https://laravel.com/docs/9.x/helpers#method-app
* base_path() returns the path of the plugins folder, something like: 'D:\www\laravel\plguins'
* $name returns the namespace of the plugin's service provider, something like: '\plugins\plugin-name\Providers\PluginNameServiceProvider'
* 'File::' is an abbreviation for the facade 'Illuminate\support\facades\File'
**/
//Import file if class not found
spl_autoload_register(function ($name) {
//Check if the file exists before importing it
if(File::exists(base_path($name). '.php')){
include(base_path($name). '.php');
}
});
//Access the plugins folder and list the directories
$folders = File::directories(base_path('plugins'));
//Iterates over a set of subfolders and accesses each one of them looking for a file with 'Provider.php' in the name
foreach($folders as $item){
//Returns the absolute path of the first service provider it finds
$str = collect(glob(base_path('plugins'). "\\". $item . '\\Providers\\*Provider.php'))->first();
//Proceed with registration if the plugin has a service provider, otherwise continue the loop
if(!is_null($str)){
//Prepare the class name and namespace to be used
$filter = pathinfo($str);
$path = $filter['dirname'] .'\\'. $filter['filename'];
$newclass = str_replace('.php', '', strstr($str, '\plugins'));
//Register the plugin provider
app()->register(new $newclass(app()));
}
}
} catch(\Exception $e){
dd($e->getMessage());
}
The problem with my code is that it is not registering the service providers whose namespace has not yet been mapped by the composer. The problem seems to be in spl_autoload_register, I say it seems because the code is in a place that 'kills' laravel in case of a fatal error so the debug options are minimal and the code cannot be moved to another place as it is included inside a package.
Current behavior
The service provider seems to have been imported due to the fact that 'include()' returns 1, however, there are two types of situations: 1) It gives the error 'class not found'; 2) It doesn't display any errors and it doesn't execute the service provider code either.
Expected behavior
The code must import the service provider and register it, so that the code present in that service provider is executed.
Plugin service provider example to be registered
<?php
namespace plugins\plugin-name\Providers;
use Illuminate\Support\ServiceProvider;
class PluginNameServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
dd(['status' => 'Registered!', 'more' => app()]);
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
I solved the problem with the modification below:
Before
//Returns the absolute path of the first service provider it finds
$str = collect(glob(base_path('plugins'). "\\". $item . '\\Providers\\*Provider.php'))->first();
After
//Returns the absolute path of the first service provider it finds
$str = collect(glob($item . '\\Providers\\*Provider.php'))->first();
I'll leave the code there in the question in case someone tries to implement a hook functionality in php and has a similar problem. If you use it, be kind and give proper credit.

REST GET with parameter ignored, PHP Symfony 3 Mpdf

Working on a REST API for PDF processor using Mpdf(and tfox symfony bundle) on Symfony 3 Framework. I created two GET requests, one with no parameters for testing, and one with the parameter(URL of the HTML file) I want to read and then convert into PDF.
The Generic GET function:
/**
*
* #Rest\Get("/create")
*/
public function createPDFAction(){
$mpdfService = $this->get('tfox.mpdfport');
$html = "<h1> Hello </h1>";
$mpdf = $mpdfService->getMpdf();
$mpdf->WriteHTML($html);
$mpdf->Output();
exit;
}
The Second GET function with parameter:
/**
* #param $htmlSource
* #Rest\Get("/create/{htmlSource}")
*/
public function createPDFFromSourceAction($htmlSource){
$mpdfService = $this->get('tfox.mpdfport');
$html = file_get_contents($htmlSource);
$mpdf = $mpdfService->getMpdf();
$mpdf->WriteHTML($html);
$mpdf->Output();
exit;
}
The problem is, when I call the second function using browser or Postman the first function is always returned instead and I get the PDF with "Hello", if I remove the first GET function, I get error "no route found for GET/create"
I investigated:
The PDF URL is correct, I manually inserted it in first function and worked
No syntax error, I copied the same function without the parameters and worked
The Calls I do are:
http://localhost:8000/create This one works
http://localhost:8000/create?htmlSource=PATH-TO-FILE-LOCALLY This one doesnot work
If I put the PATH-TO-FILE-LOCALLY in function 1 manually it works fine
So I have 2 Questions:
Since I am new to REST and LAMP, should I use GET or others ? My goal is to read the HTML form that the user will fill into a variable and pass it to Mpdf which will convert it into PDF and return that PDF for viewing or download
Why only the first GET function is being read ?
Notes: I am developing on Linux, with PHPStorm, PHP 7, Symfony 3, localhost, the html file I am testing with is on my local machine
Side point: In case this is resolved, I am supposed to upload this to my clients server (which is Apache) - do you have any guides on how to do that and what should be the URLs changed to ?
Thank you all in advance
Updates:
I have changed the functionality to POST methods and it now works fine:
/**
* #Rest\Post("/mPDF/")
*/
public function createPDFAction(Request $request){
$source = $request->get('source');
if($source == ""){
return new View('No Data found', Response::HTTP_NO_CONTENT);
}
$mpdfService = $this->get('tfox.mpdfport');
$html = file_get_contents($source);
$mpdf = $mpdfService->getMpdf();
$mpdf->WriteHTML($html);
$mpdf->Output();
exit;
}
After publishing to Apache production server and some configuration tweaks the site is now live ! - but now I am facing a new issue which I will post a new question for with all the config info I have - basically POST method is returning {
"error": {
"code": 405,
"message": "Method Not Allowed"
}
}
http://localhost:8000/create?htmlSource=PATH-TO-FILE-LOCALLY
("/create/{htmlSource}")
These paths do not match.
First path consists of domain name, and route create, while second path has route "create" + slash + wildcard.
Query parameters are not defined within routing annotation. Instead, access them inside controller, using
public function createPDFFromSourceAction(Request $request)
{
$htmlSource = $request->query->get('htmlSource'); // query string parameter
$somethingElse = $request->request->get('somethingElse'); //POST request parameter
...
}
Symfony will pass Request object inside the controller for you.
As for your other question, GET requests are usually used for things that do not change the state of the application, and POST/PUT/PATCH/DELETE requests change the state. Since you are uploading something, use POST request.
For your 'side note' you should ask another question instead.

Generating an XML Sitemap in Laravel 5

I have a laravel application that is still in the development stages. I am currently trying to generate a sitemap for the application using Spatie\Sitemap\SitemapGenerator but my code isn't working. This is my sitemap code in a file called GenerateSiteMap.php:
<?php
use Spatie\Sitemap\SitemapGenerator;
class GenerateSiteMap
{
public function generateSite()
{
$generator = SitemapGenerator::create('http://127.0.0.1:8000/')->writeToFile('sitemap.xml');
return $generator;
}
}
It doesn't give me any errors when I run it, it just doesn't do anything. Any idea how I can fix it?
If your file is at public folder you need to add public_path
$generator = SitemapGenerator::create('http://127.0.0.1:8000/')->writeToFile(
public_path('sitemap.xml'));
otherwise it might be a permission issue

Php Laravel Print paper

My website is related to flight tickets, after booking the ticket and ticket gets issued if i want to print the ticket, it is showing the paths of the buttons in agent panel like this ->
welcome agent,
Profile (http://localhost/tb/customer/dashboard)
MarkUp (http://localhost/tb/agent/markup/list)
Dashboard (localhost/tb)
reports (localhost/tb/list)
View Ticket Details
after all these, ticket details are printing.
I like DocRaptor for this kind of thing. Send an API request with some HTML/CSS/Javascript and you get back a PDF with which you can do anything you want, including presenting to the user for download/printing.
They even provide a PHP class to handle API access.
It's a pay service, but it is worth every penny.
Generating a PDF locally has never worked well for me. Between the formatting problems that arise with different libraries, lack of Javascript support, and the resources consumed by the process, it was just too inconvenient.
If you want to create PDF and then print the view, try this PDF generation plugin such as pdf-laravel. This is just a DOMPDF module for Laravel 5.
To get this pdf-laravel5 plugin, run below composer command:
composer require vsmoraes/laravel-pdf
To add provider, update config/app.php with below line to providers array:
'PDF' => 'Vsmoraes\Pdf\PdfFacade',
To generate out file:
$router->get('/pdf/output', function() {
$html = view('pdfs.example')->render();
PDF::load($html)
->filename('/tmp/example1.pdf')
->output();
return 'PDF saved';
});
Inject on your controller:
<?php namespace App\Http\Controllers;
use Vsmoraes\Pdf\Pdf;
class HomeController extends BaseControler
{
private $pdf;
public function __construct(Pdf $pdf)
{
$this->pdf = $pdf;
}
public function helloWorld()
{
$html = view('pdfs.example1')->render();
return $this->pdf
->load($html)
->show();
}
}
You can also force to download PDF like:
$router->get('/pdf/download', function() {
$html = view('pdfs.example')->render();
return PDF::load($html)->download();
});

Selective upload manager in Moodle

In Moodle 1.9.7, is it possible to somehow specify a white-list of the allowed extensions for the user uploaded files?
Looking at the source, there is no built in way to limit filetypes when modules use the upload_manager to process the uploaded files. There also is no use of any mimetype detection based on content of the files. The filelib libraries in moodle base their mimetype on file extension.
A neat way to do this for a module while is using the moodle upload manager object, would be to write a new class which extends the existing upload_manager class, and add some validatation based on file content.
Something like the following - you'll need to tidy this up a bit, and complete it with your own validation code.
class upload_manager_strict extends upload_manager {
var $allowed_types
function upload_manager_strict($inputname='', $deleteothers=false, $handlecollisions=false, $course=null, $recoverifmultiple=false, $modbytes=0, $silent=false, $allownull=false, $allownullmultiple=true, $allowed_types=null) {
$this->allowed_types = $allowed_types;
parent::upload_manager_strict($inputname, $deleteothers, $handlecollisions, $course, $recoverifmultiple, $modbytes, $silent, $allownull, $allownullmultiple)
}
function validate_file(&$file) {
$status = parent::validate_file(&$file);
if ($status) {
// do some mimetype checking and validation on the file $file['tmp_name']
// could use $this->allowedtypes
}
return $status;
}
}

Categories