UploadedFileService.php (6263B)
1 <?php 2 3 namespace PartKeepr\UploadedFileBundle\Services; 4 5 use Gaufrette\Exception\FileNotFound; 6 use Gaufrette\Filesystem; 7 use PartKeepr\UploadedFileBundle\Entity\UploadedFile; 8 use PartKeepr\UploadedFileBundle\Exceptions\DiskSpaceExhaustedException; 9 use Symfony\Component\DependencyInjection\Container; 10 use Symfony\Component\DependencyInjection\ContainerAware; 11 use Symfony\Component\HttpFoundation\File\File; 12 13 class UploadedFileService extends ContainerAware 14 { 15 /** 16 * @var Container 17 */ 18 protected $container; 19 20 public function __construct(Container $container) 21 { 22 $this->setContainer($container); 23 } 24 25 /** 26 * Replaces the current file with a new file. 27 * 28 * @param UploadedFile $file The target file 29 * @param File $filesystemFile The source file 30 */ 31 public function replace(UploadedFile $file, File $filesystemFile) 32 { 33 $this->replaceFromFilesystem($file, $filesystemFile); 34 } 35 36 /** 37 * Replaces the current file with a new file. 38 * 39 * @param UploadedFile $file The target file 40 * @param File $filesystemFile The source file 41 */ 42 public function replaceFromFilesystem(UploadedFile $file, File $filesystemFile) 43 { 44 $file->setOriginalFilename($filesystemFile->getBasename()); 45 $file->setExtension($filesystemFile->getExtension()); 46 $file->setMimeType($filesystemFile->getMimeType()); 47 $file->setSize($filesystemFile->getSize()); 48 49 $storage = $this->getStorage($file); 50 51 if ($filesystemFile->getSize() > $this->container->get('partkeepr_systemservice')->getFreeDiskSpace()) { 52 throw new DiskSpaceExhaustedException(); 53 } 54 55 $storage->write($file->getFullFilename(), file_get_contents($filesystemFile->getPathname()), true); 56 } 57 58 public function replaceFromData(UploadedFile $file, $data, $filename) 59 { 60 $tmpdir = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(); 61 $tempName = tempnam($tmpdir, 'PARTKEEPR'); 62 63 file_put_contents($tempName, $data); 64 65 $this->replaceFromFilesystem($file, new File($tempName)); 66 $file->setOriginalFilename($filename); 67 68 unlink($tempName); 69 } 70 71 public function delete(UploadedFile $file) 72 { 73 $storage = $this->getStorage($file); 74 75 try { 76 $storage->delete($file->getFullFilename()); 77 } catch (FileNotFound $e) { 78 $this->container->get('logger')->alert( 79 sprintf('Unable to delete file %s', $file->getFullFilename()), 80 [$e, $file] 81 ); 82 } 83 } 84 85 /** 86 * Replaces an existing uploaded file with another uploaded file. 87 * 88 * @param UploadedFile $target The target file 89 * @param UploadedFile $source The source file 90 */ 91 public function replaceFromUploadedFile(UploadedFile $target, UploadedFile $source) 92 { 93 $storage = $this->getStorage($source); 94 $this->replaceFromData($target, $storage->read($source->getFullFilename()), $source->getFullFilename()); 95 $target->setOriginalFilename($source->getOriginalFilename()); 96 } 97 98 /** 99 * Replaces the file from an URL. Does some tricks to avoid 403 forbidden on some sites, like setting a proper 100 * browser identification. 101 * 102 * @param UploadedFile $file The target file 103 * @param string $url The URL to replace from 104 * 105 * @throws \Exception An exception if the curl operation failed 106 * 107 * @todo Parse the filename from the return headers 108 */ 109 public function replaceFromURL(UploadedFile $file, $url) 110 { 111 /* Some sites don't like automated requests. But the internet is meant to be open for anybody, 112 * even for scripts. So we are evil and fake the headers. 113 * 114 * Credit goes to Ryan Rampersad from whom I copied most code. 115 * http://blog.ryanrampersad.com/2008/11/07/get-remote-html-with-curl-and-php/ 116 */ 117 $curl = curl_init(); 118 119 $header[0] = 'Accept: text/xml,application/xml,application/xhtml+xml,'; 120 $header[0] .= 'text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'; 121 $header[] = 'Cache-Control: max-age=0'; 122 $header[] = 'Connection: keep-alive'; 123 $header[] = 'Keep-Alive: 300'; 124 $header[] = 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7'; 125 $header[] = 'Accept-Language: en-us,en;q=0.5'; 126 $header[] = 'Pragma: '; 127 128 $browser = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 '; 129 $browser .= 'Ubuntu/8.04 (hardy) Firefox/3.0.3'; 130 131 curl_setopt($curl, CURLOPT_URL, $url); 132 curl_setopt($curl, CURLOPT_USERAGENT, $browser); 133 curl_setopt($curl, CURLOPT_HTTPHEADER, $header); 134 curl_setopt($curl, CURLOPT_AUTOREFERER, true); 135 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 136 curl_setopt($curl, CURLOPT_TIMEOUT, 30); 137 curl_setopt($curl, CURLOPT_MAXREDIRS, 7); 138 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); 139 140 $data = curl_exec($curl); 141 142 if ($data === false) { 143 $curlError = curl_error($curl); 144 // Strip ANY tags from the error message. curl tends to spit out <url> is not valid, which then 145 // confuses the error message parser on the client side. 146 $curlError = str_replace(['>', '<'], '', $curlError); 147 148 throw new \Exception('replaceFromURL error: '.$curlError); 149 } 150 151 curl_close($curl); 152 153 $this->replaceFromData($file, $data, basename($url)); 154 } 155 156 /** 157 * Returns the storage directory for a given UploadedFile. 158 * 159 * @param UploadedFile $file The file to get the storage directory for 160 * 161 * @return string The storage directory for the type of the given UploadedFile 162 */ 163 public function getStorageDirectory(UploadedFile $file) 164 { 165 return $this->container->getParameter('partkeepr.directories.'.$file->getType()); 166 } 167 168 /** 169 * @param UploadedFile $file 170 * 171 * @return Filesystem 172 */ 173 public function getStorage(UploadedFile $file) 174 { 175 $type = strtolower($file->getType()); 176 177 return $this->container->get('filesystem_'.$type); 178 } 179 }