How to download a file with RESTFUL cakePHP 2.3 - php

I am using CakePHP 2.3 and I have two apps on 2 different servers. I am required to download a file from the first server using REST. I have made my applications RestFul and have configured the routes. I am able to post, get, put and delete but I cannot get it done to download the file.
Below is a sample code for a get
public function view($id) {
$object = $this->Imodel->find('first', array('conditions' => array('Imodel.id' => $id), 'contain' => array()));
$this->set(array(
'object' => $object,
'_serialize' => array('object')
));
}
I would appreciate any help to download a file with REST, complying with the Restful architecture that I already have in place.
Edit
After some time, I finally got it to work. In case someone else runs into the same problem, the whole thing was about understanding cakePHP HttpSocket better.
So first on the server where the webservice is registered (where we download the file from), below is my function; its response is a file as explained (here)
public function getpdffile($id = NULL){
$filepath = APP. 'Files/file.pdf'; //path to the file of interest
$this->response->file($filepath);
return $this->response;
}
Since the file was not public (not in webroot), i had to use MediaView. Then after setting this, I'd retrieve it for download using HttpSocket as shown below:
public function download($id = NULL, $fileMine = 'pdf', $fileName = 'file', $download = TRUE){
$httpSocket = new HttpSocket();
$filepath = APP. 'Files/myfile.pdf';
$file = fopen($filepath, 'w');
$httpSocket->setContentResource($file);
$link = MAIN_SERVER."rest_models/getpdffile/".$id.".json";
$httpSocket->get($link);
fclose($file);
$this->response->file($filepath);
return $this->response;
}
What I did there was copy the file to the App folder of my server and render it in a view.
I hope it helps someone :-)

On the server which call the file to download :
$file = file_get_contents(urlwhereyoudownload) ;
And on the server where webservice is register :
header('Content-type: $mimetypeoffile');
header('Content-Disposition: attachment; filename=".$fileName."');
readfile("$pathtofile");exit;

Related

Correct code to set storage class on S3 objects when using Transfer

I'm using v3 of the SDK and working out the code to transfer a folder of files from a local drive to s3. Per the documentation for Transfer I'm trying to set up my options array to set the storage class to something other than the default. I found further documentation that suggests the following for setting similar parameters:
$uploader = new Transfer($s3Client, $source, $dest, [
'before' => function (\Aws\Command $command) {
// Commands can vary for multipart uploads, so check which command
// is being processed
if (in_array($command->getName(), ['PutObject', 'CreateMultipartUpload'])) {
// Set custom cache-control metadata
$command['CacheControl'] = 'max-age=3600';
// Apply a canned ACL
$command['ACL'] = strpos($command['Key'], 'CONFIDENTIAL') ### false ? 'public-read' : 'private';
}
},
]);
If I replace the Cache-Control and ACL variable settings with $command['StorageClass'] = 'REDUCED_REDUNDANCY'; I'm still not getting the desired result.
My code looks like this:
$uploader = new Transfer($s3Client, $source, $dest, [
'before' => function (\Aws\Command $command) {
// Commands can vary for multipart uploads, so check which command
// is being processed
if (in_array($command->getName(), ['PutObject', 'CreateMultipartUpload'])) {
$command['StorageClass'] = 'REDUCED_REDUNDANCY';
}
},
]);
What am I doing wrong?

How to add a redirect from the backend controller in shopware

I have created a plugin and after the other processes of the plugin are done i would like to redirect to a given url from a controller in the backend.
i have created a plugin that creates a documents from orders and that is working fine. however at the end of the process i would like to redirect to a url that can download or open the document that has been created. i know the url for doing so is structured like this (http://localhost:8000/backend/Order/openPdf?id=harshvalueforpdf). i am using shopware version 5.5.1 in docker on my local host.
public function redirectmyurlAction()
{
$harsh = "9ce6b9a9cd5d469386fbb5bd692f9644";
$search_word = $harsh;
error_log(print_r(array('Reached redirect action'), true)."\n", 3, Shopware()->DocPath() . '/test.log');
$this->redirect(
array(
'module'=> backend,
'controller' => 'Order',
'action' => 'openPdf?id='.$search_word,
)
);
}
i expect that when the process reached this action the user is redirected to the created url and then it should be able to download or show the pdf. But it logs the log i put before the redirect but does not redirect. nothing is logged in errors or console. When i put the same redirect on the frontend i get the CSRFTokenValidationException which is what i expect, but it shows the redirect works there so why not in the backend.
Update:
After the responses,i have copied the function and modified it as below but it logs everything there and still does nothing am i missing something?
public function openmyPdf($DocHarsh, $orderId)
{
error_log(print_r(array('Entered openmyPdf function',$DocHarsh,$orderId,$date), true)."\n", 3, Shopware()->DocPath() . '/error.log');
$filesystem = $this->container->get('shopware.filesystem.private');
$file = sprintf('documents/%s.pdf', basename($DocHarsh));
if ($filesystem->has($file) === false) {
error_log(print_r(array('Entered if statement, file doesnt exists ',$DocHarsh,$orderId,$date), true)."\n", 3, Shopware()->DocPath() . '/error.log');
$this->View()->assign([
'success' => false,
'data' => $this->Request()->getParams(),
'message' => 'File not exist',
]);
return;
}
// Disable Smarty rendering
$this->Front()->Plugins()->ViewRenderer()->setNoRender();
$this->Front()->Plugins()->Json()->setRenderer(false);
$orderModel = Shopware()->Models()->getRepository(Document::class)->findBy(['hash' =>$DocHarsh]);
$orderModel = Shopware()->Models()->toArray($orderModel);
$orderId = $orderModel[0]['documentId'];
$response = $this->Response();
$response->setHeader('Cache-Control', 'public');
$response->setHeader('Content-Description', 'File Transfer');
$response->setHeader('Content-disposition', 'attachment; filename=' . $orderId . '.pdf');
$response->setHeader('Content-Type', 'application/pdf');
$response->setHeader('Content-Transfer-Encoding', 'binary');
$response->setHeader('Content-Length', $filesystem->getSize($file));
$response->sendHeaders();
$response->sendResponse();
$upstream = $filesystem->readStream($file);
$downstream = fopen('php://output', 'wb');
while (!feof($upstream)) {
fwrite($downstream, fread($upstream, 4096));
}
error_log(print_r(array('leaving the pdf function',$DocHarsh,$orderId,$upstream,$downstream), true)."\n", 3, Shopware()->DocPath() . '/error.log');
}
Please have a look at backend-controller of the order module. It should be the same case. This function is used for opening/downloading a document from the backend:
https://github.com/shopware/shopware/blob/5.5/engine/Shopware/Controllers/Backend/Order.php#L1113
I think it might be confusing for backend users to be redirected (from the backend context) to a new blank page with a download.
According to my own evaluation. I think the issue you are having is because this is not an action but simply a function try making it an Action and run it through the browser like the original one.
Don't forget to whitelist it.
use the class use Shopware\Components\CSRFWhitelistAware;
then
something like this
/**
* {#inheritdoc}
*/
public function getWhitelistedCSRFActions()
{
return [
'youropenPdfActionnamewithoutthewordAction'
];
}
and also add the implements CSRFWhitelistAware to your class declaration.

Blueimp jQuery fileupload Plugin and Symfony : how to dynamically change file repository name based on an id?

I use the plugin 'blueimp jquery fileupload' to upload files in Javascript (that part I got it right) and then I have to handle the uploads on the server side using an uploadhandler affiliated to the plugin (UploadHandler.php).
Working in Symfony, I managed to create a service based on this php script and it works in my controller (the files are uploaded in the default repository, yet on my page I get the error message 'upload failed' and I don't know why but it's not a big problem I guess), but the thing is :
I would like to custom the repository path to upload the files based on the user id, and since I call the uploadhandler file as a service, I don't know how to override the options using the construct function, as I would be able to with a basic call in php.
Here's my code :
public function uploadFiles(Request $request)
{
$uploadhandler = $this->container->get('extranetcontratbundle.uploadhandler');
$response = $uploadhandler->response;
$files = $response['files'];
return new JsonResponse($files);
}
In the options of UploadHandler.php there is :
$this->options = array(
'script_url' => $this->get_full_url().'/'.$this->basename($this->get_server_var('SCRIPT_NAME')),
'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/',
'upload_url' => $this->get_full_url().'/files/',
'input_stream' => 'php://input',
'user_dirs' => false,
'mkdir_mode' => 0755,
'param_name' => 'files',
...blabla
And I would like to override the options in a similar way as I would in 'normal' php :
$tmpImagesDir = JPATH_ROOT . 'tmp' . $userId .;
$tmpUrl = 'tmp/' . $userId . '/' . '/';
$uploadOptions = array('upload_dir' => $tmpImagesDir, 'upload_url' => $tmpUrl);
$uploadHandler = new UploadHandler($uploadOptions);
But to do that I would have to write "require_once(blabla)" and I would have created the service for nothing. If I understood it right, that's not the way to do it in Symfony. Is there a way ?
Thank you for reading, please help.

Laravel Excel download not working

The problem is the same as described here Laravel Excel Download using Controller
But I just can not believe that there is no method to deal with Excel downloads in Laravel without using another resource. I was already able handle the instant downloads in controller with response() for PDFs.
Mabybe the headers are wrong? My code:
public function getFile($file) {
$path = storage_path('app/excel/exports/' . $file);
$headers = array('Content-Type' => File::mimeType($path));
return response()->download($path, $file, $headers);
}
So the excel file is created and saved correctly in my storage folder (happens before the code above). Then I use an axios.get method to download the file with the function above.
Headers I am getting:
Accept-Ranges:bytes
Cache-Control:public
Connection:keep-alive
Content-Disposition:attachment; filename="test_file.xlsx"
Content-Length:7066
Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
But whatever I do or try to change the download just won't start.
You can try with these two headers.
return response()->download($path, $file, [
'Content-Type' => 'application/vnd.ms-excel',
'Content-Disposition' => "attachment; filename='Report.xls'"
]);
Thanks,
I manged to solve it.
It seems to be not possible to solve this with a simple axios.get request to the route. Instead I needed to open the route directly with a link.
Did not work with:
HTML
<button #click="downloadExcel()">Download Table as Excel File</button>
downloadExcel() {
axios.get('/customers/export');
}
Simple solution (instead of just using axios.get):
<a :href="/customers/export"><button>Download Table as Excel File</button></a>
So it would also be possible to open the route after the axios request with:
downloadExcel() {
let newWindow = window.open();
axios.get('/customers/export')
.then(response => {
newWindow.location = 'http://' + window.location.hostname + '/customers/export';
});
}

How to download a file from URL without showing the full path in laravel?

Download link:-
<a href='"+ downloadlink + '/attachment-download/' + $('#employee_ID').val()+'/'+ res[i].file_name +"'>
Route:-
Route::get('/attachment-download/{id}/{filename}', array(
'uses' => 'AttachmentsController#getDownloadAttachments'
));
Attachment Controller:-
public function getDownloadAttachments($id,$filename){
$file="./img/user-icon.png";
$resource = \Employee::WhereCompany()->findOrfail($id);
$path = $this->attachmentsList($resource);
foreach($path as $index => $attachment){
if ($filename == $attachment['file_name']) {
$filePath = $attachment['url'];
}
}
//return \Response::download($file);
return \Response::download($filePath);
}
File URL Output:-
https://zetpayroll.s3.ap-south-1.amazonaws.com/employees/81/Screenshot%20from%202017-04-26%2015%3A07%3A45.png?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAI57OFN3HPCBPQZIQ%2F20170612%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20170612T144818Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=59ecc4d11b7ed71bd336531bd7f4ab7c84da6b7424878d6487679c97a8c52ca7
In this, if try to download the file by using a static path like
$file="./img/user-icon.png";
return \Response::download($file);
it is downloaded fine. But not possible to downloading file from AWS URL, Please help me how to down file automatically using URL. Or How to get Path from URL in laravel or PHP.
Thank you.
Using the above function all the files are being downloaded. But while trying to open the files, text, pdf, ... files open (.text, .csv, .pdf..) without problem, but images don't.
$fileContent = file_get_contents($filePath);
$response = response($fileContent, 200, [
'Content-Type' => 'application/json',
'Content-Disposition' => 'attachment; filename="'.$filename.'"',
]);
return $response;

Categories