diff --git a/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php b/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php index 22e2abfb4f..f84ae1d2ef 100644 --- a/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php +++ b/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php @@ -51,7 +51,7 @@ class FileUploadResource extends ResourceBase { * * @var string */ - const FILENAME_REGEX = '@\bfilename=\"(?.+)\"@'; + const FILENAME_REGEX = '@\bfilename(?\*?)=\"(?.+)\"@'; /** * @var \Drupal\Core\File\FileSystem @@ -192,7 +192,7 @@ public function post(Request $request, $entity_type_id, $bundle, $field_name) { $lock_id = $this->generateLockIdFromFileUri($file_uri); if (!$this->lock->acquire($lock_id)) { - throw new HttpException(500, sprintf('File "%s" is already locked for writing')); + throw new HttpException(503, sprintf('File "%s" is already locked for writing'), NULL, ['Retry-After' => 1]); } // Begin building file entity. diff --git a/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php b/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php index 920f3e78b2..cc42a53d19 100644 --- a/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/FileUploadResourceTestBase.php @@ -233,6 +233,30 @@ public function testFileUploadStrippedFilePath() { $this->assertSame($this->testFileData, file_get_contents('public://foobar/example.txt')); } + /** + * Tests using the file upload route with a unicode file name. + */ + public function testFileUploadUnicodeFilename() { + $this->initAuthentication(); + + $this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']); + + $this->setUpAuthorization('POST'); + + $uri = Url::fromUri('base:' . static::$postUri); + + $response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'file; filename="example-✓.txt"']); + + $this->assertSame(201, $response->getStatusCode()); + + $expected = $this->getExpectedNormalizedEntity(1, 'example-✓.txt', TRUE); + $this->assertResponseData($expected, $response); + + // Check the actual file data. It should have been written to the configured + // directory, not /foobar/directory/example.txt. + $this->assertSame($this->testFileData, file_get_contents('public://foobar/example-✓.txt')); + } + /** * Tests using the file upload route with a zero byte file. */ @@ -330,11 +354,13 @@ protected function getExpectedUnauthorizedAccessMessage($method) { * The file ID to load and create normalized data for. * @param string $expected_filename * The expected filename for the stored file. + * @param bool $expected_as_filename + * Whether the expected filename should be the filename property too. * * @return array * The expected normalized data array. */ - protected function getExpectedNormalizedEntity($fid = 1, $expected_filename = 'example.txt') { + protected function getExpectedNormalizedEntity($fid = 1, $expected_filename = 'example.txt', $expected_as_filename = FALSE) { $author = User::load(static::$auth ? $this->account->id() : 0); $file = File::load($fid); @@ -364,7 +390,7 @@ protected function getExpectedNormalizedEntity($fid = 1, $expected_filename = 'e ], 'filename' => [ [ - 'value' => 'example.txt', + 'value' => $expected_as_filename ? $expected_filename : 'example.txt', ], ], 'uri' => [