How to set PDF page title from Symfony Controller? - php

Here is my method in a Controller:
/**
* #Route("/bilgi/agr", name="user_agreement")
*/
public function agr(): Response
{
$response = new BinaryFileResponse(__DIR__ . '/../../public/docs/User_Agreement.pdf');
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, $response->getFile()->getFileName());
return $response;
}
I'm expecting to see Page title as User_Agreement.pdf, but instead it is agr. Which is not appropriate. I can't change the route because it is being used on several other classes/files.
Is there any way I can set a custom title or at least the file name? When I save the file I see the file name as User_Agreement.pdf so the file name is also correct.
If that is not possible is there workaround to show it in twig/html?

You can't. <title>" is an HTML element, not a PDF one.
If a browser renders a PDF directly (as many/most do nowadays), the only thing they could use for a "title" is the URL for the request. agr in your case.
It's basically something the server side has no control of. It just sends the response, and the browser decides how to show it, and what to show in the space usually reserved for the <title> element.
With the Content-Disposition header you can hint the browser about what name they should suggest for the file to the end-user, but that's all.
If you absolutely need this, yes, you could send a regular HTML response and somehow show the PDF inlined/embedded on the page.

Related

TYPO3 - How to make a get request to a controller action

I have an application in TYPO3 CMS. It has an extension test_extension that has a controller and an action. This action should return some JSON.
class TestRequestController extends ActionController
{
public function testAction(): void
{
echo json_encode([
'test' => 123
]);
}
}
I want to be able to request this action via Postman. How can I do that? TYPO3 version - 8.7. Thanks in advance!
Creating Links
Usually extbase-extensions are created with the help of the extension extension_builder. This extension creates by default templates and links to open list- and detail-view.
It's possible to add additional actions and to create according links.
Also the usage of the templates is not required and your way to return the result of the action without usage of a template is possible.
The logic of the links is this, I break the parts down in single lines:
tx_extension_plugin[controller]=TestRequest
tx_extension_plugin[action]=test
There are still more parameters commonly used like id or search, but it's also possible to define individual parameters.
In your case the listed parameters seem to be sufficient and the link would look like this now:
www.example.com/?id=123&tx_extension_plugin[controller]=TestRequest&tx_extension_plugin[action]=test
for the extension news this would look like this, this is with your parameter-values which are not available in news. This example shows only how the extension-related part is handled (tx_news_pi1):
www.example.com/?id=123&tx_news_pi1[controller]=TestRequest&tx_news_pi1[action]=test
id is for the page here and not a parameter for your extension, else id had to look like this tx_extension_plugin[id]=123. So all extension related parameters have the form tx_extension_plugin[parameter]=value.
While it's possible to create those links with the API, it's easier to create them with the view helpers for the fluid templates. Note that sometimes an hash is added at the end, like this example: &cHash=1234567890.
The cHash-value you can't create without viewHelper or API, so the knowledge about the parameters and the other values is not enough to create the links.
Calling the link
Most often links are directly called by the browser and visible in the URL-bar. But sometimes and in your case you might call the links by AJAX, so that the json is loaded without being directly shown to the user.
It's also possible to wrap the json in script-tags, so that it's every time loaded when the whole page is called, it's not dynamic then and without AJAX it can't adjust to some user-interaction without loading a whole page again.
AJAX responses can be realized in many ways in TYPO3, the most easy one is to define a special page-type and a special page in the pagetree for it. On this page you add the plugin of your extension to return the json. This "Ajax-page" has to be configured to have the correct header for Json and must not return anything else but the JSON, so all HTML-Output has to be disabled.

How to know if a url is audio or video?

I get some urls from xml rss feed. The rss makes no distinction to audio or video files, they all come from the same tag. How can I distinguish if it is a audio or video url to provide the right to play it?
I have the url stored in a var
var url = "http://www.someWeb/someFile.mp3";
I tried to make a search with jQuery:
var search = url.search(/.mp3|.m4a/i);
if (search > -1){
$('#check').text("it is audio");
}else {
$('#check').text("it is video");
}
it works most of the cases but it could be more types of audio files, there could always be some types of audio, without extension...
Is there a better way to know if a url is a audio or file?
You might be able to use the php function get_headers(). You can test this out by using it to grab one of your links and doing a print_r() to see what you get under the "Content-type" key.
If that works, just go ahead and create an switch case for all your file types and you should be good to go
http://php.net/manual/en/function.get-headers.php
This is a shot in the dark, but if you need to know the content type before loading it, you can try a HEAD request:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4
This is only if the content service supports it though. Of course if you wrote the service then you can implement this yourself. Simply send the headers, but omit the actual content.
On the receiving end the response headers should include 'Content-Type'.
From this you can extract the type of content being delivered. It typically looks like this:
text/plain
image/jpeg
video/mp4
audio/mp3
It is simple enough to determine the general media from the prefix.
You must get HTTP header fields (Content-Type for this case). Look here: http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
This is a bit of a dificult one.
I faced the same issue, loading content from an RSS feed, that could contain either video or audio.
There is no way to know what is the content without actually requesting it, and as I'm consuming content from external websites, I can't know for sure if they support the HEAD method.
what I'm currently doing is assuming the URL ends in a filename, taking the extension and using the browser ready version of https://github.com/broofa/node-mime to get the corresponding MIME type.
After getting the MIME type I check if it starts with either 'video' or 'audio'.
Here is the code:
function isVideoByURL(url) {
var filename = url.split('/').pop().split('#')[0].split('?')[0];
if(filename) {
var ext = filename.split('.').pop();
var mimeType = mime.getType(ext);
return mimeType.startsWith('video');
}
return false;
}

Magento Controller displaying big XML file causes odd rendering in Browser

I am working on a relatively extensive but not huge XML file that is being delivered from a custom Module in Magento using a controller. Everything has been going well and I have been able to get it to work and add nodes with no issues. The browser (Chrome in this case) has been rendering the XML document fine and stylizing it as expected. In order to display the XML headers properly via Magento I am using the following code:
/* Set display to render output as an XML document */
$this->loadLayout(false);
$this->getResponse()->setHeader('Content-Type','text/xml');
echo "<Magento >";
.
.
.
echo "</Magento>\n";
$this->renderLayout();
When the output reaches 140 nodes, it stops rendering as formatted XML and just shows the data as if it is being rendered as HTML and doesn't know the node definition. Example:
If I comment a node out so there are 139 it will render properly. If I save the full 140+ node XML page as a file then drop that file into Chrome, it renders properly. For Example:
If I run the 140+ node XML file through a validator it comes through as valid XML code. I also get the same result of a broken rendering display if I use Firefox instead to view the page.
The question. Is there a limit as to how big an XML file can be to have it be delivered via a Magento Controller? If so, can I reset this limit to more than 139 nodes so this renders properly? Conversely, should I not worry about if the browser is rendering the page properly because it is going to be used by a different program and not a browser?
Check your header with curl. My guess it it's not being set.
curl -I http://example.com
Try setting your header directly with
header('Content-Type: text/xml');
Setting a header on the response object will only impact content that's delivered via the response object. Since you're echoing code directly, the response object never gets the chance to send its headers.
Both Chrome and Firefox have a set of heuristics that attempt to guess how a document should be rendered. Even with a text/html header a short XML document may be detected as XML, triggering XML rendering. Once it reachers a certain length, the browsers guess that's it's an HTML document, and the HTML rendering engine takes over.
Ensuring your header is set correctly should solve the problem.
Usually this problem happens when you break a tag (not close it) or insert characters not supported. Unknown size limitations of XML, perhaps your browser validation is crashing.

How to get new CAPTCHA image in kohana

I'm using kohana 3.0 with kolanos-kohana-captcha-2ba7a6a module from earlier versions. Everything works fine, but I can't figure out one thing: how do I create new captcha image for current form? For example user can't read characters and clicks 'new image'. The ajax is sent, but the response is (almost always) the same image. In the controller, I tried the following:
echo new Captcha_Basic;
Captcha::instance()->__destruct();
echo Captcha::instance();
echo $captcha->generate_challenge();
and even some more, but it's almost(??) always the same image. I even tried to delay image loading on client-side, but nothing works. Any suggestions?
I had the same problem and I have solved it by simply editing system/libraries/drivers/Captcha.php file. I have changed the image_render() function so that a random string is passed as a GET parameter in the src attribute's url.
I reckon that though ajax is not caching, the browser is caching the image's src url. Every ajax call to generate a new image does indeed generate a new image. However, the src attribute the CAPCHA library returns is always the same, causing the browser to simply show the same image it has cached. Including a randomly generated string as a GET parameter causes the browser to fetch the new image.

Download part of HTML page as text (PHP)

So I have an 'export' application that arrives the user at an end page with a textarea with lots of text. Now the workflow is to copy and paste that text from the textarea into a file.
The exported code is getting larger, and we want to encourage users to do this more often, so the copy/paste route is no longer desirable. (Not to mention that my xterm->ssh->screen->vi chain doesn't paste 250K characters so well)
So the problem is this: I have a textarea that has exported code in it, and I want to provide a button that is 'Download this Code to a file'
I'm fairly sure that I will have to hit the server again, but I just want to check all my bases. The ways I can think of doing this (sending generated textarea value as a file ot the browser)
Create a script that receives said text as a POST and sends it back with the right Content Headers. This is no desirable because we would be POSTing 250k, which would be slower than:
Create a script that regenerates the text area and provide a button the original page that hits the scripts and downloads the file. This is the option I am leaning towards
Use Javascript somehow and perhaps beable to skip the server all together and just send the $('.exported').val() to the browser with the right headers? Not sure how to do this atm.
So if anyone has suggestions that'd be great, maybe I'm overlooking something. Thanks!
edit: Download textarea contents as a file using only Javascript (no server-side)
This question says the JS route is not possible (probable)
I would go with option 2. Simplest and fastest. The other ones are a bit contrived.
If you go with option 2, why even leave the textarea at all?
I would suggest the following: make your button replace the whole DOM of the page with your text. After that, user will be able to simply press Ctrl+S or ⌘S. Not exactly what you want, but still a shortcut.
I guess you can do it with the following (jQuery):
$ (document.body).html ($ ('#textarea-id').html)
(Not tested)
Following your second option, you could trigger your script with a keyword to send the data as attachment.
Here’s an example of how it could look like:
if (isset($_GET['download'])) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment;filename="dump.data"');
echo $data;
exit;
} else {
echo '<textarea>', htmlspecialchars($data), '</textarea>';
}
options:
TEXT ALREDY IN THE SERVER:
MAKE A GETFILE.PHP that reponse that text in a file.
TEXT IN THE CLIENT
POST THE TEXT TO A GETFILE.PHP and response the file.
POST THE TEXT TO A GETFILE.PHP, storage the file and provide a LINK to DOWNLOAD (then you could delete or not the file, depending of your needs)
Here is some example of this
http://www.osix.net/modules/article/?id=773

Categories