Silverstripe 3.2:如何使用按钮强制从 CMS 下载文件?
Silverstripe 3.2: How to force a download of a file from the CMS with a button?
我在通过单击 CMS 中的按钮下载 pdf 文件时遇到问题。我正在使用模块 BetterButtons。按钮本身工作正常,但下载文件时出错。我总是收到此错误:
Failed to load resource: the server responded with a status of 500
(Warning at line 257 of
/Applications/MAMP/htdocs/myproject/framework/control/HTTPResponse.php)
和
[Recoverable Error] Object of class SS_HTTPResponse could not be
converted to string.
所以我假设行
return SS_HTTPRequest::send_file($filedata, $fileName,
'application/pdf');
错误或 $filedata 有问题...正确的方法是什么?
我的代码:
在我有下载按钮的数据对象中:
private static $better_buttons_actions = array (
'printFilesPDF'
);
public function getBetterButtonsActions() {
$fields = parent::getBetterButtonsActions();
$fields->push(BetterButtonCustomAction::create('printFilesPDF', 'Print files'));
return $fields;
}
public function printFilesPDF() {
$filedata = File::find("assets/PDF/myFile.pdf");
$fileName = "myFile.pdf";
return SS_HTTPRequest::send_file($filedata, $fileName, 'application/pdf');
}
您打算将字符串传递给 send_file 函数,而不是传递 "File" 对象。
我会更改行
$filedata = File::find("assets/PDF/myFile.pdf");
至
$filedata = file_get_contents(File::find("assets/PDF/myFile.pdf")->getFullPath());
但是,最好写成检查 File::find(...) returns 一个文件而不是 null!
File::find() returns 如果文件存在则为 File 对象,否则为 null。它从不 returns 二进制数据,这就是 HTTPResponse 不会将其转换为字符串的原因。
如果 file_get_contents 不工作,请检查它是否在您的机器上被禁用。
//attempt to find the file
$file = File::find("path/to/my/file.txt");
//you need to check that the file is File and not null
if($file && $file instanceof File) {
//get the file path
$path = $file->getFullPath();
//get the file data. If file_get_contents() doesn't work, you might need fopen() or file() instead
$fileData = file_get_contents($path);
$fileName = "myFile.pdf";
return SS_HTTPRequest::send_file($fileData, $fileName, 'application/pdf');
}
我找到了解决办法。它不是最好的,但对我有用。
我让文件在新选项卡中打开,这样用户就可以自己下载或者直接在浏览器中查看 window:
首先我没有使用 BetterButtonCustomAction
,而是使用 BetterButtonLink
:
public function getBetterButtonsActions() {
$fields = parent::getBetterButtonsActions();
$fields->push(new BetterButtonLink('Download the file', "assets/myfile.pdf"));
}
通过使用 BetterButtonLink
我遇到了以下问题:
每次我单击按钮时,它都会尝试通过 AJAX 请求在 CMS 管理员中打开 PDF,这会导致显示编码文本。您可以在这里找到一个简单的解决方案:https://github.com/unclecheese/silverstripe-gridfield-betterbuttons/issues/64
所以我的最终代码是
public function getBetterButtonsActions() {
$fields = parent::getBetterButtonsActions();
$fields->push(new BetterButtonLink_NewWindow('Download the file', "assets/myfile.pdf"));
}
和 BetterButtonLink_NewWindow
代码:
class BetterButtonLink_NewWindow extends BetterButtonLink {
/**
* Gets the HTML representing the button
* @return string
*/
public function getButtonHTML() {
return sprintf(
'<a class="ss-ui-button %s" href="%s" target="_blank">%s</a>',
$this->extraClass(),
$this->getButtonLink(),
$this->getButtonText()
);
}
}
我们可以使用 LiteralField
来创建一个 link 文件。通过将 link 的 class 设置为 ss-ui-button
我们可以使 link 看起来像一个按钮。
这里是一个示例 link 特定文件:
LiteralField::create(
'DownloadLink',
'<a href="assets/myfile.pdf" target="_blank" class="ss-ui-button" download>Download the file</a>'
);
这可以在 getCMSFields
或 getCMSActions
中使用,使按钮显示在字段区域或按钮区域。
这里是一个例子 link 通过 getCMSFields
到 $has_one
受控文件:
public function getCMSFields() {
$fields = parent::getCMSFields();
if ($this->File()->exists()) {
$fields->addFieldToTab('Root.Main',
LiteralField::create(
'DownloadLink',
'<a href="' . $this->File()->Link() . '" target="_blank" class="ss-ui-button" download>Download the file</a>'
)
);
}
return $fields;
}
我在通过单击 CMS 中的按钮下载 pdf 文件时遇到问题。我正在使用模块 BetterButtons。按钮本身工作正常,但下载文件时出错。我总是收到此错误:
Failed to load resource: the server responded with a status of 500 (Warning at line 257 of /Applications/MAMP/htdocs/myproject/framework/control/HTTPResponse.php)
和
[Recoverable Error] Object of class SS_HTTPResponse could not be converted to string.
所以我假设行
return SS_HTTPRequest::send_file($filedata, $fileName, 'application/pdf');
错误或 $filedata 有问题...正确的方法是什么?
我的代码:
在我有下载按钮的数据对象中:
private static $better_buttons_actions = array (
'printFilesPDF'
);
public function getBetterButtonsActions() {
$fields = parent::getBetterButtonsActions();
$fields->push(BetterButtonCustomAction::create('printFilesPDF', 'Print files'));
return $fields;
}
public function printFilesPDF() {
$filedata = File::find("assets/PDF/myFile.pdf");
$fileName = "myFile.pdf";
return SS_HTTPRequest::send_file($filedata, $fileName, 'application/pdf');
}
您打算将字符串传递给 send_file 函数,而不是传递 "File" 对象。
我会更改行
$filedata = File::find("assets/PDF/myFile.pdf");
至
$filedata = file_get_contents(File::find("assets/PDF/myFile.pdf")->getFullPath());
但是,最好写成检查 File::find(...) returns 一个文件而不是 null!
File::find() returns 如果文件存在则为 File 对象,否则为 null。它从不 returns 二进制数据,这就是 HTTPResponse 不会将其转换为字符串的原因。
如果 file_get_contents 不工作,请检查它是否在您的机器上被禁用。
//attempt to find the file
$file = File::find("path/to/my/file.txt");
//you need to check that the file is File and not null
if($file && $file instanceof File) {
//get the file path
$path = $file->getFullPath();
//get the file data. If file_get_contents() doesn't work, you might need fopen() or file() instead
$fileData = file_get_contents($path);
$fileName = "myFile.pdf";
return SS_HTTPRequest::send_file($fileData, $fileName, 'application/pdf');
}
我找到了解决办法。它不是最好的,但对我有用。
我让文件在新选项卡中打开,这样用户就可以自己下载或者直接在浏览器中查看 window:
首先我没有使用 BetterButtonCustomAction
,而是使用 BetterButtonLink
:
public function getBetterButtonsActions() {
$fields = parent::getBetterButtonsActions();
$fields->push(new BetterButtonLink('Download the file', "assets/myfile.pdf"));
}
通过使用 BetterButtonLink
我遇到了以下问题:
每次我单击按钮时,它都会尝试通过 AJAX 请求在 CMS 管理员中打开 PDF,这会导致显示编码文本。您可以在这里找到一个简单的解决方案:https://github.com/unclecheese/silverstripe-gridfield-betterbuttons/issues/64
所以我的最终代码是
public function getBetterButtonsActions() {
$fields = parent::getBetterButtonsActions();
$fields->push(new BetterButtonLink_NewWindow('Download the file', "assets/myfile.pdf"));
}
和 BetterButtonLink_NewWindow
代码:
class BetterButtonLink_NewWindow extends BetterButtonLink {
/**
* Gets the HTML representing the button
* @return string
*/
public function getButtonHTML() {
return sprintf(
'<a class="ss-ui-button %s" href="%s" target="_blank">%s</a>',
$this->extraClass(),
$this->getButtonLink(),
$this->getButtonText()
);
}
}
我们可以使用 LiteralField
来创建一个 link 文件。通过将 link 的 class 设置为 ss-ui-button
我们可以使 link 看起来像一个按钮。
这里是一个示例 link 特定文件:
LiteralField::create(
'DownloadLink',
'<a href="assets/myfile.pdf" target="_blank" class="ss-ui-button" download>Download the file</a>'
);
这可以在 getCMSFields
或 getCMSActions
中使用,使按钮显示在字段区域或按钮区域。
这里是一个例子 link 通过 getCMSFields
到 $has_one
受控文件:
public function getCMSFields() {
$fields = parent::getCMSFields();
if ($this->File()->exists()) {
$fields->addFieldToTab('Root.Main',
LiteralField::create(
'DownloadLink',
'<a href="' . $this->File()->Link() . '" target="_blank" class="ss-ui-button" download>Download the file</a>'
)
);
}
return $fields;
}