Skip to content

Commit 8f0e217

Browse files
committed
ACP2E-1627: [Cloud] Magento Product Recommendation/Data Services Causing File Download Warning
1 parent 64368a7 commit 8f0e217

File tree

2 files changed

+232
-62
lines changed

2 files changed

+232
-62
lines changed

lib/internal/Magento/Framework/App/Response/File.php

Lines changed: 108 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Magento\Framework\App\Http\Context;
1313
use Magento\Framework\App\PageCache\NotCacheableInterface;
1414
use Magento\Framework\App\Request\Http as HttpRequest;
15+
use Magento\Framework\Exception\FileSystemException;
1516
use Magento\Framework\Filesystem;
1617
use Magento\Framework\Filesystem\Driver\File\Mime;
1718
use Magento\Framework\Session\Config\ConfigInterface;
@@ -24,6 +25,8 @@
2425
*/
2526
class File extends Http implements NotCacheableInterface
2627
{
28+
private const DEFAULT_RAW_CONTENT_TYPE = 'application/octet-stream';
29+
2730
/**
2831
* @var Http
2932
*/
@@ -83,49 +86,55 @@ public function __construct(
8386
$this->filesystem = $filesystem;
8487
$this->mime = $mime;
8588
$this->options = array_merge($this->options, $options);
89+
if (!isset($this->options['filePath'])) {
90+
if (!isset($this->options['fileName'])) {
91+
throw new InvalidArgumentException("File name is required.");
92+
}
93+
$this->options['contentType'] ??= self::DEFAULT_RAW_CONTENT_TYPE;
94+
}
8695
}
8796

8897
/**
8998
* @inheritDoc
9099
*/
91100
public function sendResponse()
92101
{
93-
$dir = $this->filesystem->getDirectoryWrite($this->options['directoryCode']);
94-
if (!isset($this->options['filePath'])) {
95-
throw new InvalidArgumentException("File path is required.");
96-
}
97-
if (!$dir->isExist($this->options['filePath'])) {
98-
throw new InvalidArgumentException("File '{$this->options['filePath']}' does not exists.");
102+
$dir = $this->filesystem->getDirectoryRead($this->options['directoryCode']);
103+
$forceHeaders = true;
104+
if (isset($this->options['filePath'])) {
105+
if (!$dir->isExist($this->options['filePath'])) {
106+
throw new InvalidArgumentException("File '{$this->options['filePath']}' does not exists.");
107+
}
108+
$filePath = $this->options['filePath'];
109+
$this->options['contentType'] ??= $dir->stat($filePath)['mimeType']
110+
?? $this->mime->getMimeType($dir->getAbsolutePath($filePath));
111+
$this->options['contentLength'] ??= $dir->stat($filePath)['size'];
112+
$this->options['fileName'] ??= basename($filePath);
113+
} else {
114+
$this->options['contentLength'] = mb_strlen((string) $this->response->getContent(), '8bit');
115+
$forceHeaders = false;
99116
}
100-
$filePath = $this->options['filePath'];
101-
$contentType = $this->options['contentType']
102-
?? $dir->stat($filePath)['mimeType']
103-
?? $this->mime->getMimeType($dir->getAbsolutePath($filePath));
104-
$contentLength = $this->options['contentLength']
105-
?? $dir->stat($filePath)['size'];
106-
$fileName = $this->options['fileName']
107-
?? basename($filePath);
117+
108118
$this->response->setHttpResponseCode(200);
109-
$this->response->setHeader('Content-type', $contentType, true)
110-
->setHeader('Content-Length', $contentLength, true)
111-
->setHeader('Content-Disposition', 'attachment; filename="' . $fileName . '"', true)
112-
->setHeader('Pragma', 'public', true)
113-
->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true)
114-
->setHeader('Last-Modified', date('r'), true);
115-
116-
$this->response->sendHeaders();
117-
118-
if (!$this->request->isHead()) {
119-
$stream = $dir->openFile($filePath, 'r');
120-
while (!$stream->eof()) {
121-
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
122-
echo $stream->read(1024);
123-
}
124-
$stream->close();
125-
if ($this->options['remove']) {
126-
$dir->delete($filePath);
119+
$this->response->setHeader('Content-Type', $this->options['contentType'], $forceHeaders)
120+
->setHeader('Content-Length', $this->options['contentLength'], $forceHeaders)
121+
->setHeader(
122+
'Content-Disposition',
123+
'attachment; filename="' . $this->options['fileName'] . '"',
124+
$forceHeaders
125+
)
126+
->setHeader('Pragma', 'public', $forceHeaders)
127+
->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', $forceHeaders)
128+
->setHeader('Last-Modified', date('r'), $forceHeaders);
129+
130+
if (isset($this->options['filePath'])) {
131+
$this->response->sendHeaders();
132+
if (!$this->request->isHead()) {
133+
$this->sendFileContent();
134+
$this->afterFileIsSent();
127135
}
128-
$this->response->clearBody();
136+
} else {
137+
$this->response->sendResponse();
129138
}
130139
return $this;
131140
}
@@ -155,4 +164,70 @@ public function clearHeader($name)
155164
$this->response->clearHeader($name);
156165
return $this;
157166
}
167+
168+
/**
169+
* @inheritDoc
170+
*/
171+
public function setBody($value)
172+
{
173+
$this->response->setBody($value);
174+
return $this;
175+
}
176+
177+
/**
178+
* @inheritDoc
179+
*/
180+
public function appendBody($value)
181+
{
182+
$this->response->appendBody($value);
183+
return $this;
184+
}
185+
186+
/**
187+
* @inheritDoc
188+
*/
189+
public function getContent()
190+
{
191+
return $this->response->getContent();
192+
}
193+
194+
/**
195+
* @inheritDoc
196+
*/
197+
public function setContent($value)
198+
{
199+
$this->response->setContent($value);
200+
return $this;
201+
}
202+
203+
/**
204+
* Sends file content to the client
205+
*
206+
* @return void
207+
* @throws FileSystemException
208+
*/
209+
private function sendFileContent(): void
210+
{
211+
$dir = $this->filesystem->getDirectoryRead($this->options['directoryCode']);
212+
$stream = $dir->openFile($this->options['filePath'], 'r');
213+
while (!$stream->eof()) {
214+
// phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
215+
echo $stream->read(1024);
216+
}
217+
$stream->close();
218+
}
219+
220+
/**
221+
* Callback after file is sent to the client
222+
*
223+
* @return void
224+
* @throws FileSystemException
225+
*/
226+
private function afterFileIsSent(): void
227+
{
228+
if ($this->options['remove']) {
229+
$dir = $this->filesystem->getDirectoryWrite($this->options['directoryCode']);
230+
$dir->delete($this->options['filePath']);
231+
}
232+
}
158233
}

0 commit comments

Comments
 (0)