function getFileMD5sum($path) { if (is_file($path)) { return PHP_BigFile::getMd5Sum($path); } else { return false; } }
/** * Set path to file for download * * The Last-Modified header will be set to files filemtime(), actually. * Returns PEAR_Error (HTTP_DOWNLOAD_E_INVALID_FILE) if file doesn't exist. * Sends HTTP 404 status if $send_404 is set to true. * * @access public * @return mixed Returns true on success or PEAR_Error on failure. * @param string $file path to file for download * @param bool $send_404 whether to send HTTP/404 if * the file wasn't found */ function setFile($file, $send_404 = true) { $file = realpath($file); if (!Codendi_File::isFile($file)) { if ($send_404) { $this->HTTP->sendStatusCode(404); } return PEAR::raiseError("File '{$file}' not found.", HTTP_DOWNLOAD_E_INVALID_FILE); } $this->setLastModified(filemtime($file)); $this->file = PHP_BigFile::stream($file); $this->size = Codendi_File::getSize($file); return true; }
function testWithBigFile() { //$this->assertTrue(is_writeable($this->writePath), "$this->writePath should be writable"); $writeFile = fopen(PHP_BigFile::stream($this->writePath), 'wb'); $this->assertTrue($writeFile); $file = new FRSFile(); $file->file_location = $this->readPath; $fileSize = PHP_BigFile::getSize($this->readPath); $chunkSize = 8 * 1024 * 1024; $nbChunks = ceil($fileSize / $chunkSize); for ($i = 0; $i < $nbChunks; $i++) { $data = $file->getContent($i * $chunkSize, $chunkSize); $written = fwrite($writeFile, $data); $this->assertEqual(strlen($data), $written); } $this->assertIdentical(md5_file($this->readPath), md5_file($this->writePath)); }
/** * Compares the local and the distant checksums and throw an error if they are different */ function checkChecksum($group_id, $item_id, $filename) { $this->setSoapCommand('getDocmanFileMD5sum'); $soap_params = array('group_id' => $group_id, 'item_id' => $item_id); $local_checksum = PHP_BigFile::getMd5Sum($filename); // For very big files, the checksum can take several minutes to be computed, so we set the socket timeout to 10 minutes $default_socket_timeout = ini_set('default_socket_timeout', 600); $distant_checksum = $GLOBALS['soap']->call('getDocmanFileMD5sum', $soap_params, $this->use_extra_params()); //revert default_socket_timeout if ($default_socket_timeout !== false) { ini_set('default_socket_timeout', $default_socket_timeout); } if ($local_checksum == $distant_checksum) { echo "File uploaded successfully\n"; } else { echo "ERROR: Local and remote checksums are not the same. You should remove the document on the server, and try to create it again.\n"; } }
/** * Computes the md5sum for a given file * * @param String $filePath * * @return String */ public function computeFRSMd5Sum($filePath) { return PHP_BigFile::getMd5Sum($filePath); }
function getIncomingFileMd5Sum($file) { return PHP_BigFile::getMd5Sum($file); }
/** * Create a new file based on given objects * * Given a "transient" file object, physically move the file from it's landing zone to * it's release area and create the corresponding entry in the database. * * @param FRSFile $file File to create * * @return FRSFile */ public function createFile(FRSFile $file, $extraFlags = self::COMPUTE_MD5) { $rule = new Rule_FRSFileName(); if (!$rule->isValid($file->getFileName())) { throw new FRSFileIllegalNameException($file); } $rel = $file->getRelease(); if ($this->isFileBaseNameExists($file->getFileName(), $rel->getReleaseID(), $rel->getGroupID())) { throw new FRSFileExistsException($file); } if ($this->isSameFileMarkedToBeRestored($file->getFileName(), $rel->getReleaseID(), $rel->getGroupID())) { throw new FRSFileToBeRestoredException($file); } clearstatcache(); $filePath = $this->getSrcDir($rel->getProject()) . '/' . $file->getFileName(); if (!file_exists($filePath)) { throw new FRSFileInvalidNameException($file); } if (0 != ($extraFlags & self::COMPUTE_MD5)) { $file->setComputedMd5(PHP_BigFile::getMd5Sum($filePath)); if (!$this->compareMd5Checksums($file->getComputedMd5(), $file->getReferenceMd5())) { throw new FRSFileMD5SumException($file); } } $file->setFileSize(PHP_BigFile::getSize($filePath)); $file->setStatus('A'); if ($this->moveFileForge($file)) { $fileId = $this->create($file->toArray()); if ($fileId) { $file->setFileID($fileId); return $file; } else { throw new FRSFileDbException($file); } } else { throw new FRSFileForgeException($file); } }
return true; } else { return false; } break; case SEEK_END: if ($this->filesize + $offset >= 0) { $this->offset = $this->filesize + $offset; return true; } else { return false; } break; default: return false; } } /** * Retrieve information about a file resource * * This method is called in response to fstat(). * * @return array @see http://php.net/stat */ public function stream_stat() { return stat($this->path); } } PHP_BigFile::register();
/** * Returns the content of the file, in a raw resource * * +2GB safe * * @return mixed the content of the file */ function getContent($offset = 0, $size = -1) { if ($size == -1) { $size = $this->getFileSize(); } $path = PHP_BigFile::stream(realpath($this->getFileLocation())); return file_get_contents($path, false, NULL, $offset, $size); }
function soapCall($soap_params, $use_extra_params = true) { // Prepare SOAP parameters $callParams = $soap_params; unset($callParams['remote_name']); unset($callParams['output']); $callParams['offset'] = 0; $callParams['chunk_size'] = $GLOBALS['soap']->getFileChunkSize(); $startTime = microtime(true); $totalTran = 0; $i = 0; do { $callParams['offset'] = $i * $GLOBALS['soap']->getFileChunkSize(); $content = base64_decode($GLOBALS['soap']->call($this->soapCommand, $callParams, $use_extra_params)); if ($i == 0) { $this->manageOutput($soap_params, $output, $fd); } $cLength = strlen($content); if ($output !== false) { $written = fwrite($fd, $content); if ($written != $cLength) { throw new Exception('Received ' . $cLength . ' of data but only ' . $written . ' written on Disk'); } } else { echo $content; } $totalTran += $cLength; $i++; } while ($cLength >= $GLOBALS['soap']->getFileChunkSize()); $endTime = microtime(true); $GLOBALS['LOG']->add('File download completed'); $transRate = $totalTran / ($endTime - $startTime); $GLOBALS['LOG']->add('Transfer rate: ' . size_readable($transRate, null, 'bi', '%.2f %s/s')); if ($output !== false) { fclose($fd); unset($callParams['offset']); unset($callParams['chunk_size']); $fileInfo = $GLOBALS['soap']->call('getFileInfo', $callParams, $use_extra_params); if ($fileInfo->computed_md5) { $GLOBALS['LOG']->add('Compute downloaded file\'s md5 sum'); $localChecksum = PHP_BigFile::getMd5Sum($output); if ($localChecksum != $fileInfo->computed_md5) { exit_error("File transfer faild: md5 checksum locally computed doesn't match remote one ({$fileInfo->computed_md5})"); } else { echo "File retrieved successfully (md5 checksum verified).\n"; } } else { echo "File retrieved successfully.\n"; } } }
function before_soapCall(&$loaded_params) { $this->soapCommand = 'addUploadedFile'; if (!$loaded_params['others']['uploaded_file'] && !$loaded_params['others']['local_file']) { exit_error("You must specify a file name with either the --local_file or --uploaded_file parameter, depending the way you want to add the file."); } else { if (!$loaded_params['others']['local_file']) { // we will test if the file is present in the incoming directory $uploaded_files = $GLOBALS['soap']->call("getUploadedFiles", array('group_id' => $loaded_params['soap']['group_id'])); if (!in_array($loaded_params['others']['uploaded_file'], $uploaded_files)) { exit_error("File '" . $loaded_params['others']['uploaded_file'] . "' not found in incoming directory."); } $loaded_params['soap']['filename'] = $loaded_params['others']['uploaded_file']; } else { $localFileLocation = $loaded_params['others']['local_file']; if (!file_exists($localFileLocation)) { exit_error("File '" . $localFileLocation . "' doesn't exist"); } else { if (!is_readable($localFileLocation)) { exit_error("Could not open '" . $localFileLocation . "' for reading"); } else { // TODO : use PHP_BigFile //$path = PHP_BigFile::stream(realpath($localFileLocation)); $path = realpath($localFileLocation); $GLOBALS['LOG']->add('Calculating md5 checksum of the file ...'); $loaded_params['soap']['reference_md5'] = PHP_BigFile::getMd5Sum($path); $GLOBALS['LOG']->add('Md5 checksum calculated.'); $offset = 0; $chunkSize = $GLOBALS['soap']->getFileChunkSize(); $startTime = microtime(true); $totalTran = 0; $i = 0; /* During this loop the file in construction in the incoming directory * may be corrupted by concurrent access, such as releasing it * or use of addFileChunk again with the same filename. * This corruption will be automatically detected at the end of upload * when comparing the md5 sums and file will not be released. */ do { $offset = $i * $chunkSize; $contents = file_get_contents($path, false, NULL, $offset, $chunkSize); $cLength = strlen($contents); $contents = base64_encode($contents); if ($i == 0) { $firstChunk = true; } else { $firstChunk = false; } $addedSize = $GLOBALS['soap']->call("addFileChunk", array('filename' => basename($path), 'contents' => $contents, 'first_chunk' => $firstChunk)); if ($addedSize == $cLength) { $totalTran += $cLength; $i++; } else { exit_error("Upload of the file failed"); } } while ($cLength >= $chunkSize); $endTime = microtime(true); $transRate = $totalTran / ($endTime - $startTime); $GLOBALS['LOG']->add('Transfer rate: ' . size_readable($transRate, null, 'bi', '%.2f %s/s')); $loaded_params['soap']['filename'] = basename($loaded_params['others']['local_file']); $loaded_params['soap']['is_upload'] = true; } } } // sort the parameters in the right order uksort($loaded_params['soap'], array($this, "sort_parameters")); } }
function soapCall($soap_params, $use_extra_params = true) { // Prepare SOAP parameters $callParams = $soap_params; unset($callParams['remote_name']); unset($callParams['output']); $callParams['chunk_offset'] = 0; $callParams['chunk_size'] = $GLOBALS['soap']->getFileChunkSize(); $startTime = microtime(true); $totalTran = 0; $i = 0; do { $callParams['chunk_offset'] = $i * $GLOBALS['soap']->getFileChunkSize(); $content = base64_decode($GLOBALS['soap']->call($this->soapCommand, $callParams, $use_extra_params)); if ($i == 0) { $this->manageOutput($soap_params, $output, $fd); } $cLength = strlen($content); if ($output !== false) { $written = fwrite($fd, $content); if ($written != $cLength) { throw new Exception('Received ' . $cLength . ' of data but only ' . $written . ' written on Disk'); } } else { echo $content; } $totalTran += $cLength; $i++; } while ($cLength >= $GLOBALS['soap']->getFileChunkSize()); $endTime = microtime(true); $transRate = $totalTran / ($endTime - $startTime); $GLOBALS['LOG']->add('Transfer rate: ' . size_readable($transRate, null, 'bi', '%.2f %s/s')); // Finish! if ($output !== false) { fclose($fd); unset($callParams['chunk_offset']); unset($callParams['chunk_size']); //Check the md5sum $localChecksum = PHP_BigFile::getMd5Sum($output); $remoteChecksum = $GLOBALS['soap']->call('getDocmanFileMD5sum', $callParams, $use_extra_params); if ($localChecksum == $remoteChecksum) { echo "File retrieved successfully.\n"; } else { exit_error("Local and remote checksums are not the same. Try to download it again.\n"); } } }