I am trying to (1) upload a image file (2) resize it and center it and (3) change the file name and (4) move it into /public dir.
Here is a part of my code;
$path = $this->request->getFile('dh_site_logo')->store();
$temp_file_path = WRITEPATH.'uploads/' . $path;
service('image')
->withFile($temp_file_path) // must include full path
->fit(250,150,'center')
->save($temp_file_path);
$public_file_path = ROOTPATH.'public';
$file_to_upload = 'site_logo.'.$update_post->guessExtension();;
$overwrite = true;
$update_post->move($public_file_path, $file_to_upload, $overwrite);
I assume I would have to do the image manipulation in the writable/uploads
directory prior to moving to /public
I cant seem to lock on to the file that has been uploaded with a new random name, manipulate and then move.
Tried this, too
// example of return $path = "20220130/1643544458_5a528551d1fe83c88e02.gif"
$path = $this->request->getFile('dh_site_logo')->store('site_logo', 'site_logo.gif');
$temp_file_path = WRITEPATH.'uploads/' . $path;
service('image')
->withFile($temp_file_path) // must include full path
->fit(250,150,'center')
->save($temp_file_path);
$public_file_path = ROOTPATH.'public';
$new_file_name = 'site_logo.gif';
$overwrite = true;
$update_post->move($public_file_path, $new_file_name, $overwrite);
The above give me an error, The uploaded file has already been moved
Ci4 / Image Upload and Manipulate Error / finfo_file(/tmp/phpSrVWUZ): failed to open stream: No such file or directory
You're receiving the above error because of the line of code below:
$file_to_upload = 'site_logo.'.$update_post->guessExtension();;
On your first line of code below:
$path = $this->request->getFile('dh_site_logo')->store();
You're calling the CodeIgniter\HTTP\Files\UploadedFile::store(?string $folderName = null, ?string $fileName = null) method which saves the uploaded file (/tmp/phpSrVWUZ
) to a new location.
I.e: The store(...)
method moves the uploaded file from the server's default temporary directory (/tmp
) to the project's upload directory (WRITEPATH . 'uploads/'
).
You then try calling $update_post->guessExtension()
forgetting that the UploadedFile instance $update_post
still refers to the old non-existent path (/tmp/phpSrVWUZ
), hence the error.
To be more specific, the method CodeIgniter\HTTP\Files\UploadedFile::guessExtension() calls another method CodeIgniter\Files\File::getMimeType(). The method getMimeType(...)
tries to retrieve the mime type using the code snippet below on a non-existent file resulting in the error:
finfo_file(finfo_open(FILEINFO_MIME_TYPE), "/tmp/phpSrVWUZ");
// PHP Warning: finfo_file(/tmp/phpSrVWUZ): Failed to open stream: No such file or directory in ...
Tried this, too
...
The above give me an error,
The uploaded file has already been moved
You normally receive this error because you're trying to move the uploaded file to a new location more than once.
This happens when you call the CodeIgniter\HTTP\Files\UploadedFile::store(...)
or CodeIgniter\HTTP\Files\UploadedFile::move(...)
method more than once.
Excerpt from CI 4.x source code.
/**
* Move the uploaded file to a new location.
* ...
* If this method is called more than once, any subsequent calls MUST raise
* an exception.
* ...
*/
public function move(...): bool {
// ...
if ($this->hasMoved) {
throw HTTPException::forAlreadyMoved();
}
// ...
}
To be more specific, every UploadedFile instance has a property called protected $hasMoved = false;
which gets updated to true
once the uploaded file has been moved successfully from the server's default temporary directory:
Excerpt from CI 4.x source code.
/**
* Returns whether the file has been moved or not. If it has,
* the move() method will not work and certain properties, like
* the tempName, will no longer be available.
*/
public function hasMoved(): bool;
This applies if you don't care about the original uploaded file and you're only interested in the final transformed/resized file residing in the 'public' path.
public function createThumbnail(\CodeIgniter\HTTP\Files\UploadedFile $uploadedFile, ?string $newThumbnailFileName = null, int $width = 250, int $height = 150, string $position = "center"): ?\CodeIgniter\Files\File
{
if (!$uploadedFile->isValid()) {
return null;
}
$newThumbnailFileName = $newThumbnailFileName
? ((($point = strrpos($newThumbnailFileName, ".")) === false) ? $newThumbnailFileName : substr($newThumbnailFileName, 0, $point)) . $uploadedFile->guessExtension()
: $uploadedFile->getRandomName();
$targetPath = ROOTPATH . 'public' . DIRECTORY_SEPARATOR . $newThumbnailFileName;
\Config\Services::image()
->withFile($uploadedFile->getRealPath() ?: $uploadedFile->__toString())
->fit($width, $height, $position)
->save($targetPath);
return new \CodeIgniter\Files\File($targetPath, true);
}
The function above basically leaves the original uploaded file in the server's default temporary directory untouched and processes a new image which gets saved in the project's 'public' path.
The function above returns a CodeIgniter\Files\File instance representing the newly transformed image. I.e:
$requestFileName = "dh_site_logo";
$uploadedFile = $this->request->getFile($requestFileName);
// Generates a thumbnail in the 'public' path with a uniquely generated filename.
$thumbnail = $this->createThumbnail(
uploadedFile: $uploadedFile
);
// OR
// Generates a thumbnail in the 'public' path with a custom filename ('site_logo').
$thumbnail = $this->createThumbnail(
uploadedFile: $uploadedFile,
newThumbnailFileName: "site_logo"
);
// OR
// You can modify the default parameters as well.
$thumbnail = $this->createThumbnail(
uploadedFile: $uploadedFile,
width: 100,
height: 150,
position: "left"
);
This applies if for some reason you want to transform/resize and save the modified image in the 'public' path similar to Solution A and still persist/keep or move the original uploaded file from the server's temporary directory to your project's writable/uploads
folder for future reference or purposes.
TIP: The file will be deleted from the temporary directory at the end of the request if it has not been moved away or renamed. - Excerpt From PHP Doc: Example #2 Validating file uploads
Steps:
writable/uploads
folder.
$requestFileName = "dh_site_logo";
$uploadedFile = $this->request->getFile($requestFileName);
// 1. Generate as many thumbnails (transformed files) as you need.
// Generates a thumbnail in the 'public' path with
// a uniquely generated filename.
$thumbnail = $this->createThumbnail(
uploadedFile: $uploadedFile
);
// 2. Lastly, move the uploaded file from the server's default temporary
// directory to the project's 'writable/uploads' folder (I.e: $uploadedFile->store()).
if (!$uploadedFile->hasMoved()) {
// The moved uploaded file.
$file = new \CodeIgniter\Files\File(WRITEPATH . 'uploads/' . $uploadedFile->store(), true);
}