this question is related to: Laravel - Force download with response()->download($fileLocation) not working
The problem is, that I use a axios GET request (as mentioned in that thread) to initiate the browser download but it is not working. My Controller works perfectly and it returns the file correctly as I can see in the browser console:
The request:
The response
The image
But the browser is not starting any download.
I am using Vue/Nuxt on client-side and the axios request is called like this:
download ({
dispatch,
commit,
rootState,
rootGetters
}) {
this.$axios.get('api/download',
{
params: {
filenames: rootGetters['files/getDownloadFilenames'],
mode: rootState.config.mode
}
}).then((response) => {
console.log(response)
}).catch((error) => {
console.log(error)
})
}
And the controller #laravel is called with the "getFileDownload" function:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class DownloadController extends Controller
{
public function getFileDownload(Request $request) {
$filenames = $request->input('filenames');
$mode = $request->input('mode');
$filePaths = [];
foreach($filenames as $filename) {
if ($mode == 'clean') {
array_push($filePaths, $request->user()->getName() . config('filesystems.transfer_out_clean') . '/' . $filename);
return response()->download($filePaths[0]);
}
}
}
}
The reason I am using an array here is that later on I want to return a ZIP file containing multiple files, but as you can see I am just using the first path to return a single file for testing purposes.
So my question is: Why isn't this request starting a download of that image file on the client even if I use a GET request?
Any help much appreciated!
Related
Why I need to put /1 in front of the url for put (update) in codeigniter 4 version 4.2.6 ?
routes.php :
$routes->resource('ApiManageProfile', ['controller' =>'App\Controllers\ApiData\ApiManageProfile']); // get, put, create, delete
ApiManageProfile.php
<?php
namespace App\Controllers\ApiData;
use App\Controllers\BaseController;
use CodeIgniter\RESTful\ResourceController;
use Codeigniter\API\ResponseTrait;
class ApiManageProfile extends ResourceController
{
use ResponseTrait;
function __construct()
{
}
// equal to get
public function index()
{
}
// equal to post
public function create() {
}
// equal to get
public function show($id = null) {
}
// equal to put
public function update($id = null) {
$id = $this->request->getVar('id');
$birthday = $this->request->getVar('birthday');
$phonenumber = $this->request->getVar('phonenumber');
echo "TESTING";
}
// equal to delete
public function delete($id = null) {
}
}
Then I use postman to call put with /1 :
https://testing.id/index.php/ApiManageProfile/1?id=71&phonenumber=1122211&birthday=2023-01-20
The code run correctly.
But if I use postman to call put without /1 :
https://testing.id/index.php/ApiManageProfile?id=71&phonenumber=1122211&birthday=2023-01-20
Then I got this error :
"title": "CodeIgniter\\Exceptions\\PageNotFoundException",
"type": "CodeIgniter\\Exceptions\\PageNotFoundException",
"code": 404,
"message": "Can't find a route for 'put: ApiManageProfile'.",
For the previous version codeigniter 4 Version 4.1.2 it is working without a problem
I cannot change all my Rest API to use /1 in front of the url for put because my Application is already launch. If I change the code in react native it will need a time to update the application. And people cannot update the data.
Codeigniter 4 seem change something in newest update version 4.2.6. Causing my routes broken in the application.
Seriously need help for this. What I can do ?
$routes->resource('ApiManageProfile', ['controller' =>'\App\Controllers\ApiData\ApiManageProfile']); // get, put, create, delete
generates RESTFUL routes including the following for the PUT action.
$routes->put('ApiManageProfile/(:segment)', '\App\Controllers\ApiData\ApiManageProfile::update/$1');
The segment isn't optional.
If you would like to implement the segment to be optional, exclude it from the generated routes and declare it explicitly that way.
$routes->resource(
'ApiManageProfile',
['controller' =>'\App\Controllers\ApiData\ApiManageProfile', 'except' => 'update']
); // get, create, delete
$routes->put(
'ApiManageProfile',
'\App\Controllers\ApiData\ApiManageProfile::update'
);
I have a file download function that works well on Firefox and Safari, but if I try to download the same file on Chrome or MS Edge, the file is downloaded without an extension.
Here's the function
public function download_chapter_file(Downloadable $downloadable, Request $request): StreamedResponse
{
if (!$request->hasValidSignature()) abort(401);
$headers = ['Content-Type' => 'application/'.$downloadable->type];
return Storage::download($downloadable->path,$downloadable->title,$headers);
}
$downloadable->type is either excel or pdf.
$downloadable->path is the full file path. eg storage/app/public/downloadable/chapters/9/ycCjt0K911x3b1aFjX8i0S9Jj8.pdf
I have tried using
return response()->download(); but it does not solve the problem.
I'd appreciate your help.
try this , it work with me :-
$headers = array(
'Content-Type: application/pdf',
);
return Response::download($downloadable->path,$downloadable->title,$headers);
After hours of trials. I finally got a working solution.
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\StreamedResponse;
class StorageController extends Controller
{
public function download_chapter_file(Downloadable $downloadable, Request $request):StreamedResponse
{
if (!$request->hasValidSignature()) abort(401);
$extension = File::extension(storage_path('app/'. $downloadable->path));
$filename = $downloadable->title.'.'.$extension;
return Storage::download($downloadable->path,$filename);
}
}
Thank you all for trying
I am using maatwebsite to export the records to CSV file. Using php laravel for backend.
Here is my following code:
Controller code:
public static function exportCsvReport($params){
header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
return Excel::download(new UsersExport, 'invoices.xlsx');
}
UserExport model:
<?php
namespace App\Exports;
use App\Models\Api\v1\Tbcall;
use Maatwebsite\Excel\Concerns\FromCollection;
class UsersExport implements FromCollection
{
public function collection()
{
return Tbcall::where('Row_Id',14407)->get();
}
}
?>
React code:
exportReporttoCsv(params){
this.setState({ isDataFetched: true }, async () => {
let productsData = await this.apiService.exportCsvReport(params);
const url = window.URL.createObjectURL(new Blob([productsData.data]));
const link = document.createElement('a');
link.setAttribute('href', 'data:text/csv');
link.href = url;
link.setAttribute('download', 'aaa1.csv'); //or any other extension
document.body.appendChild(link);
link.click();
});
}
Output:
Tried in notepad as well. Still shows the encoded data.
File is getting downloaded but when opening the file shows like these.
Not getting what is going wrong. What changes are needed here ? Any answers will be appreciated. Thanks
#Nkunj Can you open in notepad and see, issue must be in your excel settings.
ok you can try this :
http://danml.com/download.html
In Laravel I use this route
Route::get('admin/showBill/{file}','Admin\FileController#showBill');
and this code
class FileController extends AuthController
{
public function showBill($file)
{
$path = storage_path('app/bills/' . basename($file) );
if(!\File::exists($path)) return back();
return response()->file($path);
}
to display a pdf from my storage folder.
So if I have the pdf bill-1.pdf in my /storage/app/bills/ folder, then I can view it with the url
example-domain.com/admin/showBill/bill-1.pdf
The problem is that if I open that pdf with the browser, replace it, and refresh (F5) the page, then the old bill is shown. I guess its because its stored in the cache. Can I force Laravel to show the new replaced file?
I tried
public function showBill($file)
{
$path = storage_path('app/bills/' . basename($file) );
if(!\File::exists($path)) return back();
$path .= '?v='. time();
return response()->file($path);
}
But then Laravel tells me that this file does not exist. I am looking for a solution where I have not to rename the pdf file.
Are you sure you're replacing the right file?
If so, place this dd(). I've created an endpoint, response an empty pdf file - viewed it - replaced it with a content-filled pdf file and it works just fine when I replace it.
Edit: Also, you should validate the $file variable, using either a formrequest or validating in the controller.
public function showBill($file)
{
$path = storage_path('app/bills/' . basename($file));
if(!\File::exists($path)) {
dd("Quite possibly the problem is here, on the redirect back");
}
return response()->file($path);
}
this is a call to a controllers function :
function downloadFile(fn,con)
{
var loadUrl = "/Fast-Docs/index.php/Docs/downloadFile";
alert('hi');
$.post(
loadUrl,
{content: con, filename: fn});
}
controllers function :
public function downloadFile()
{
$this->load->helper('download');
$content=$this->input->post('content');
$fn=$this->input->post('filename');
return force_download($fn,$content);
}
but file is not downloading.
i know the reason why its not working but i dnt know how to fix it. so whats the solution. you need some more info , feel free to ask.
I don't completely understand what you are trying to do. Anyway, there is a fundamental problem in your code.
You are doing an ajax request to the "/Fast-Docs/index.php/Docs/downloadFile" URL, but you are ignoring the response.
My suggestion is: forget about ajax and use a simple link.
Download file
Then in the controller:
public function downloadFile($filename)
{
//Validate file name
if($filename != 'validFileName') die('Invalid file name');
//Set headers
$this->load->helper('download');
$content = file_get_contents('/images/' . $filename);
force_download($filename, $content);
}
If for some reason you can't use a link, you can redirect to the download page (by setting window.location).
If you really need to use ajax, give a look at this.