У меня есть скрипт, который генерирует файл для загрузки через ajax. Мне нужно контролировать этот запрос, потому что не все должны иметь возможность скачать файл. Процесс выглядит так:

  1. Слушайте событие щелчка, отправьте запрос ajax с данными на сервер
  2. Запрос обрабатывается, если все в порядке, создается временный файл, первая строка которого является именем файла, а дальнейшее содержимое - это содержимое файла для загрузки.
  3. Отправьте URL-адрес вновь созданного файла обратно в функцию ajax и заполните скрытый атрибут src iframe этой конечной точкой.
  4. Когда вызывается конечная точка, метод контроллера проверяет, существует ли файл, открывает его и помещает первую строку в переменную $filename с помощью array_shift, а остальное содержимое помещает в $content переменная,
  5. Установите заголовки для загрузки и выведите переменную $content.

Почему-то это работает не так, как ожидалось. Это не из-за iframe, потому что, когда я посещаю URL-адрес в браузере, Chrome сообщает мне об ошибке ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION. Я использую Laravel и не вижу, где я установил ложные заголовки?

Скрипт загрузки на данный момент:

public function download($fileId)
{
    $file = $this->tempFilesPath . $fileId;

    if (file_exists($file)) {
        $data         = explode("\n", file_get_contents($file));
        //@unlink($file);

        $fileName  = array_shift($data);
        $content   = implode("\n", $data);

        header('Content-Type: application/force-download');
        header('Content-Disposition: attachment; filename=' . $fileName);

        echo $content;
        exit;
    }
}

Сброс значений $fileName и $content показывает ожидаемые значения.

Предложения? Благодарю.

php
1
Ben Fransen 1 Май 2016 в 11:39

2 ответа

Лучший ответ

После небольшого дополнительного поиска я нашел сообщение что пишет об этой конкретной ошибке. Это произошло потому, что я форматировал имя файла датой, содержащей запятую, что расстраивало Chrome. Изменено соглашение об именах файлов, и теперь оно работает. Я оставлю вопрос онлайн, если кто-нибудь еще может столкнуться с таким поведением позже.

Для тех, кто ищет решения в будущем:

Сначала я назвал файл $filename = 'download_' . date('d-m-Y, H:i:s') . '.ext', но причиной проблемы была запятая в формате даты. Оставьте это, и вы сможете сделать еще один шаг к решению вашей проблемы.

4
Ben Fransen 1 Май 2016 в 09:45

Вы можете изменить свой метод загрузки следующим образом:

public function download($fileId) {
    $file     = $this->tempFilesPath . $fileId;

    if (file_exists($file)) {
        //$data           = explode("\n", file_get_contents($file));
        //@unlink($file);
        //$content    = implode("\n", $data);   
        //$fileName   = array_shift($data);
        $size         = @filesize($file);

        //ADD THESE FEW LINES
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');

        //header('Content-Type: application/force-download');
        header('Content-Disposition: attachment; filename=' . $fileId);
        header('Content-Transfer-Encoding: binary');

        //header('Content-Length: ' . $size);

        readfile($file);
        return TRUE;
    }
}
2
Poiz 1 Май 2016 в 09:39