I want to create a cookie after a file download.
This is an extension on the existing module: https://www.drupal.org/project/file_utility
Each time you click on a download, a popup opens. For me it is fine to have the visitors e-mail address once. Then direct download is possible without showing the popup again on other download pages.
This part of code is not generating a cookie .. why?
EDIT: $c_response->send(); was missing here.
$c_response = new \Symfony\Component\HttpFoundation\Response();
$c_response->headers->setCookie(new \Symfony\Component\HttpFoundation\Cookie('foo', 'bar'));
$c_response->send();
// Get cookie value
$c_request = new \Symfony\Component\HttpFoundation\Request();
$c_value = $c_request->cookies->get('foo');
if($c_value) {
\Drupal::logger('file_utility')->notice($c_value);
} else {
\Drupal::logger('file_utility')->notice("cookie foo is empty");
}
This is the function where the download logic happens: In this function, first I need to check if the cookie exists. If so, direct download can start. If not, popup must be initiated. The first time, the cookie will be empty.
public function downloadAction() {
// Get cookie value
$c_request = new \Symfony\Component\HttpFoundation\Request();
$c_value = $c_request->cookies->get('foo');
\Drupal::logger('file_utility')->notice("cookie: " . $c_value);
if ($c_value) {
\Drupal::logger('file_utility')->notice($c_value);
} else {
\Drupal::logger('file_utility')->notice("cookie foo is empty");
}
/** set cookie if $c_value is empty **/
$c_response = new \Symfony\Component\HttpFoundation\Response();
$c_response->headers->setCookie(new \Symfony\Component\HttpFoundation\Cookie('foo2', 'bar2'));
$c_response->send();
/** end set cookie **/
if (!isset($_GET['f_path'])) {
return;
}
// Process download.
$f_path_encoded = \Drupal::request()->query->get('f_path');
$full_path = base64_decode(urldecode($f_path_encoded));
$force_download = \Drupal::request()->query->get('force_download');
$response['file_name'] = basename($full_path);
$uid = \Drupal::currentUser()->id();
$user = User::load($uid);
if ($user->hasPermission('file download access') && $force_download == '1') {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($response['file_name']) . '"');
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: public');
// Flush system output buffer.
flush();
} elseif ($user->hasPermission('file download access') && $force_download == '0') {
$response = new RedirectResponse($full_path);
$response->send();
die;
} else {
$url = $full_path;
if (strpos($full_path, 'sites/default') !== FALSE) {
throw new AccessDeniedHttpException();
} else {
$response = new RedirectResponse($url);
$response->send();
die;
}
}
}
Extra: Can I set the cookie after the formsubmit? I found that you can add a response to a form_state but that is also not setting the cookie. I have added the first 3 lines in below function, but that is not working at the moment.
/**
* AJAX callback handler that displays any errors or a success message.
*/
public function submitUserInfoFormAjax(array $form, FormStateInterface $form_state) {
$c_response = new \Symfony\Component\HttpFoundation\Response();
$c_response->headers->setCookie(new \Symfony\Component\HttpFoundation\Cookie('john', 'do'));
$form_state->setResponse($c_response);
$response = new AjaxResponse();
$value = $form_state->getValues();
//$name = $value['name'];
$email = $value['email'];
$user_ip = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : \Drupal::request()->getHost();
$f_path_encoded = \Drupal::request()->query->get('f_path');
$f_path = base64_decode(urldecode($f_path_encoded));
$force_download = \Drupal::request()->query->get('force_download');
// If there are any form errors, re-display the form.
if ($form_state->hasAnyErrors()) {
$response->addCommand(new ReplaceCommand('#status_message_div', $form));
} else {
$status = parent::save($form, $form_state);
$entity = $this->entity;
$response->addCommand(new RedirectCommand('/filedownload?f_path=' . $f_path_encoded . '&force_download=' . $force_download));
$response->addCommand(new CloseModalDialogCommand());
}
return $response;
}
Important notice for making the cookie available for javascript:
httponly must be set to false in the constructor.
$response->headers->setCookie(new \Symfony\Component\HttpFoundation\Cookie('_john', 'do', time() + 3600, '/', '.yourdomain.com', false, false));