1. Go to this page and download the library: Download gravitypdf/upload library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
gravitypdf / upload example snippets
use GravityPdf\Upload\File;
use GravityPdf\Upload\Storage\FileSystem;
use GravityPdf\Upload\Validation\FileType;
use GravityPdf\Upload\Validation\Size;
// Store uploads where the web server will not execute or serve them directly
$storage = new FileSystem('/path/to/uploads');
// Reads $_FILES['avatar']
$file = new File('avatar', $storage);
// upload() refuses to run unless at least one validation is added
$file->addValidations([
new FileType('png', 'image/png'), // extension and file contents must both say PNG
new Size('2M'), // max 2 MiB ("B", "K", "M" or "G")
]);
// isValid() also checks is_uploaded_file(), so call it before reading any metadata
if ($file->isValid() === false) {
foreach ($file->getErrors() as $message) {
echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'), '<br>'; // always escape on output
}
return;
}
// Store under a random name; keep the client's (sanitized) name for display only
$displayName = $file->getNameWithExtension();
$file->setName(bin2hex(random_bytes(16)));
try {
$file->upload();
// $displayName is what you show; $storedPath is where the bytes are
$storedPath = $file->getUploadedLocators()[0];
} catch (\Exception $e) {
// Validation has already passed, so this is a storage failure: the destination
// exists, the extension is blocked, or the disk is full
}
$data = [
'name' => $file->getNameWithExtension(), // sanitized client name; display only
'extension' => $file->getExtension(),
'mime' => $file->getMimetype(), // sniffed from the contents, not the client's claim
'size' => $file->getSize(), // bytes, or false if the file is unreadable
'hash' => $file->getHash(), // sha256 unless you pass another algorithm
'dimensions' => $file->getDimensions(), // ['width' => int, 'height' => int]
];
use GravityPdf\Upload\File;
use GravityPdf\Upload\Storage\FileSystem;
use GravityPdf\Upload\Validation\FileType;
$storage = new FileSystem('/path/to/uploads');
// A form posted without the field at all leaves no key, which the constructor throws
// InvalidArgumentException for
if (isset($_FILES['attachment']) === false) {
return;
}
$file = new File('attachment', $storage);
// Empty for a field with nothing selected, whether it takes one file or many
if (count($file) === 0) {
return;
}
$file->addValidations([new FileType('pdf', 'application/pdf')]);
if ($file->isValid() === false) {
// Something was chosen and it was rejected: report $file->getErrors()
return;
}
$file->upload();
use GravityPdf\Upload\File;
use GravityPdf\Upload\Storage\FileSystem;
use GravityPdf\Upload\Validation\FileType;
use GravityPdf\Upload\Validation\Size;
$storage = new FileSystem('/path/to/uploads');
$file = new File('photos', $storage);
$file->addValidations([
// One format per call, otherwise every extension is paired with every media type
(new FileType(['jpg', 'jpeg'], 'image/jpeg'))
->allow('png', 'image/png')
->allow('webp', 'image/webp'),
new Size('10M'),
]);
// An empty collection has nothing to fail validation, so check the count as well
if (count($file) === 0 || $file->isValid() === false) {
foreach ($file->getErrors() as $message) {
echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'), '<br>';
}
return;
}
// Rename each file server-side, keeping the client names for display
$manifest = [];
foreach ($file as $photo) {
$displayName = $photo->getNameWithExtension();
$photo->setName(bin2hex(random_bytes(16)));
$manifest[] = [
'display' => $displayName,
'stored' => $photo->getNameWithExtension(),
'hash' => $photo->getHash(),
];
}
try {
$file->upload();
} catch (\Exception $e) {
// Multi-file uploads are not atomic: earlier files may already be on disk.
// getUploadedLocators() lists what was written so the batch can be rolled back.
// unlink() is right for Storage\FileSystem, which returns local paths. A storage
// of your own returns whatever locator it defines, so undo it the way it stores.
foreach ($file->getUploadedLocators() as $uploadedPath) {
unlink($uploadedPath);
}
return;
}
// No isValid() bail-out here: uploadValid() validates, stores what passed, and
// reports the rest afterwards
if (count($file) === 0) {
// A transfer that failed outright (too large, nothing selected) leaves the
// collection empty, and its message is already in getErrors()
foreach ($file->getErrors() as $message) {
echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'), '<br>';
}
return;
}
try {
if ($file->uploadValid() === false) {
// At least one file was rejected; the rest are stored
foreach ($file->getErrors() as $message) {
echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'), '<br>';
}
}
} catch (\Exception $e) {
// Storage failures only, which still abort the batch
return;
}
// Loop over the files that were stored, keyed by collection offset
foreach ($file->getUploadedLocators() as $offset => $storedPath) {
// $file[$offset] is the file stored at $storedPath
}
use GravityPdf\Upload\FileList;
$list = new FileList($fileInfos, $storage, $failures);
$list = new FileList(['avatar' => $avatarFile, 'banner' => $bannerFile], $storage);
$list->addValidation(new FileType(['jpg', 'jpeg'], 'image/jpeg'));
$keys = $list->getSourceKeys(); // ['avatar', 'banner']
// An empty collection throws, as on the $_FILES path: check before uploading
if (count($list) === 0) {
return $list->getErrors();
}
$list->uploadValid();
foreach ($list->getUploadedLocators() as $offset => $storedPath) {
// $keys[$offset] is the field this file was submitted under
}
class TmpUploadFile extends GravityPdf\Upload\FileInfo
{
/** A tmp directory only this application writes to. Declared once: the bridge writes
into it, and this check trusts nothing outside it. */
public const DIRECTORY = '/var/lib/myapp/uploads-tmp';
public function isUploadedFile(): bool
{
$tmp = realpath(self::DIRECTORY); // resolve both sides, or a symlinked
$path = realpath($this->getPathname()); // mount never matches
return $tmp !== false && $path !== false
&& strpos($path, $tmp . '/') === 0 // trailing /, or uploads-tmp-old passes
&& is_file($path);
}
}
$storage = (new FileSystem('/path/to/uploads'))->acceptFilesNotUploadedByPhp();
foreach ($list as $file) {
@unlink($file->getPathname()); // no-op for the ones storage already moved
}
use GravityPdf\Upload\FileInfoInterface;
$file->beforeUpload(static function (FileInfoInterface $fileInfo): void {
$fileInfo->setName(bin2hex(random_bytes(16)));
});
$file->afterUpload(static function (FileInfoInterface $fileInfo): void {
error_log(sprintf('Stored upload as %s', $fileInfo->getNameWithExtension()));
});
use GravityPdf\Upload\ErrorCode;
foreach ($file->getErrorDetails() as $error) {
if ($error['code'] === ErrorCode::SIZE_TOO_LARGE) {
$response['retry_with_smaller_file'] = true;
}
}