CodeIgniter Forums
Download file only when click on link in foreach loop - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Using CodeIgniter (https://forum.codeigniter.com/forum-5.html)
+--- Forum: General Help (https://forum.codeigniter.com/forum-24.html)
+--- Thread: Download file only when click on link in foreach loop (/thread-67345.html)



Download file only when click on link in foreach loop - wolfgang1983 - 02-12-2017

When I click on my preview button it downloads my file But I only want to be able to force download when I click on the path link in the foreach loop on view.

Question how can I force download when I click on a link in my foreach loop on view. Currently when I click on my preview button it downloads link which is wrong.

I have a attachments array on controller.

PHP Code:
<div class="panel panel-default">
<
div class="panel-heading"><h1 class="panel-title">Preview</h1></div>
<
div class="panel-body">
<
div class="row">
<
div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<?
php echo $message;?>
</div>
</div>

<div class="row">
<?php foreach ($attachments as $attachment) {?>
<div class="col-lg-2 col-md-2 col-sm-2 col-xs-12">
<!-- Click link below to download.-->
<a class="<?php echo $attachment['path'];?>"><?php echo $attachment['file_name'];?></a>
</div>
<?php }?>
</div>

</div>
</div> 

Controller


PHP Code:
<?php

class Preview extends MX_Controller {

    public function __construct() {
        parent::__construct();
        $this->load->library('parsedown');
        $this->parsedown->setLiteralBreaks(true);
        $this->load->helper('download');
    }

    public function index() {

        if ($this->input->post('newthread_preview')) {

            $data['message'] = $this->parsedown->text($this->input->post('message'));

            $data['attachments'] = array();

            $results $this->get_attachments($this->input->post('post_code'));

            if ($results) {

                foreach ($results as $result) {

                    $url base_url() . 'uploads/' $result['attachment_name'];
                    $path FCPATH 'uploads/' $result['attachment_name'];

                    $data['attachments'][] = array(
                        'file_name' => $result['file_name'],
                        'path' => $this->downloadFile($path)
                    );
                }

            }

            $this->load->view('template/forum/newthread_preview_view'$data);
        }
    }

    public function get_attachments($post_code) {
        $this->db->where('post_code'$post_code);
        $query $this->db->get($this->db->dbprefix 'attachments');

        if ($query->num_rows() > 0) {
            return $query->result_array();
        } else {
            return FALSE;
        }
    }

    public function downloadFile($attachment_name) {
        return force_download($attachment_nameNULL);
    }




RE: Download file only when click on link in foreach loop - Wouter60 - 02-12-2017

You're talking about a preview button. Where is it? I can't find it in your view.

To force download of the links that are being displayed by the foreach loop, you need a slightly different approach.
Replace the '<a> ... </a>' part with:
PHP Code:
<?php echo anchor('preview/downloadfile/' $attachment['id'], $attachment['file_name']); ?>

Instead of $attachment['id'], it may be even safer to work with something like $attachment['code'], which is a unique 32 character random string (see String Helper). That way, you neither reveal the entire path where your attachments are stored, nor the id of the attachments in your database.

You will have to adjust the preview/downloadfile method to the new situation. It will get the id or code of the file as a parameter. Use that to look up the path in your database. Use that to actually force downloading the file. By the way, it's good practice to keep all your methods (in controllers) lower case only.

On more tip: you can use the alternative php syntax in your views to improve readability:
PHP Code:
<?php foreach ($attachments as $attachment) : ?>
   //...
<?php endforeach; ?>



RE: Download file only when click on link in foreach loop - wolfgang1983 - 02-13-2017

(02-12-2017, 11:55 PM)Wouter60 Wrote: You're talking about a preview button. Where is it? I can't find it in your view.

To force download of the links that are being displayed by the foreach loop, you need a slightly different approach.
Replace the '<a> ... </a>' part with:
PHP Code:
<?php echo anchor('preview/downloadfile/' $attachment['id'], $attachment['file_name']); ?>

Instead of $attachment['id'], it may be even safer to work with something like $attachment['code'], which is a unique 32 character random string (see String Helper). That way, you neither reveal the entire path where your attachments are stored, nor the id of the attachments in your database.

You will have to adjust the preview/downloadfile method to the new situation. It will get the id or code of the file as a parameter. Use that to look up the path in your database. Use that to actually force downloading the file. By the way, it's good practice to keep all your methods (in controllers) lower case only.

On more tip: you can use the alternative php syntax in your views to improve readability:
PHP Code:
<?php foreach ($attachments as $attachment) : ?>
   //...
<?php endforeach; ?>


On the view I have now changed the attachments to like and on my controller function I have added exit; is that OK.

Seems to download now.

PHP Code:
<div class="row">
<?
php foreach ($attachments as $attachment) {?>
<div class="col-lg-2 col-md-2 col-sm-2 col-xs-12">
<?php if ($attachment['type'] == 'php') {?>

<p class="text-center">
<a href="<?php echo base_url('preview/downloads/' $attachment['attachment_id'] .'/'$attachment['attachment_name']);?>">
<img  class="img-thumbnail" style="cursor: pointer;" width="100%" height="110" src="<?php echo base_url('assets/images/icons/attachment_icons/1486989423_php.png');?>" id="download_<?php echo $attachment['attachment_id'];?>">
</p>

<p class="text-center">
<?php echo $attachment['file_name'];?>
</p>


</div> 

And on controller function


PHP Code:
public function downloads() {
      force_download(FCPATH 'uploads/' $this->uri->segment(4) . '/' $this->uri->segment(5), NULL);

     exit;




RE: Download file only when click on link in foreach loop - Wouter60 - 02-13-2017

Why uri_segment()?
PHP Code:
public function downloads($id)
{

$this->db->where('attachment_id',$id);
$query $this->db->get('attachments');
If (
$query->num_rows() == 0) {
 
  Return false;
}

$attachment $query->row();
$path $attachment->path //assuming path end with a /
$file $attachment->file_name 

Force_download
($path $fileNULL);
}
//no exit needed 

In your view, replace the '<a>...</a>' part with:
PHP Code:
<?php echo anchor('preview/downloads/' $attachment['id'], $attachment['file_name');?>
Don't include the file name in the url. A file name may contain spaces or other characters that are not allowed in url's. Fetch the file name (and path) from the database.
The anchor helper function accepts 2 or 3 parameters.
1 = the link to the controller/method (the function will convert this the actual url)
2 = the text to click on (can be an image)
3 = string with additional attributes, like class, title, style etc.