如何使用 PHP 中的服务帐户将文件上传到 Google Drive?

2023-12-28

快速入门:在 PHP 中运行云端硬盘应用程序 https://developers.google.com/drive/web/quickstart/quickstart-php似乎使用的是过时版本的 [google-api-php-client][2],而且它也没有提供有关如何使用服务帐户上传文件的示例。

在我的项目中,我需要使用服务帐户添加文件(电子表格)、添加电子表格、与其他用户共享电子表格并向电子表格添加行。

我可以获得一个空的电子表格列表,但我无法弄清楚如何使用服务帐户上传文件。

PHP 类 google-api-php-client/examples/spreadsheet.php:

<?php
    use Google\Spreadsheet\DefaultServiceRequest;
    use Google\Spreadsheet\ServiceRequestFactory;
    use Google\Spreadsheet\SpreadsheetService;
    define('JPATH_PLATFORM',1);

    require_once realpath(dirname(__FILE__) . '/../autoload.php');


    class GoogleSpreadSheet
    {
        protected $data;
        protected $client_id            = null ; //Client ID
        protected $service_account_name = null; //Email Address
        protected $key_file_location    = null; //key.p12
        protected $client               = null;
        protected $aplication_name      = null;
        protected $_errors = array();
        protected $scopes = array(    'https://www.googleapis.com/auth/drive'
                                    , 'https://www.googleapis.com/auth/drive.appdata'
                                    , 'https://www.googleapis.com/auth/drive.apps.readonly'
                                    , 'https://spreadsheets.google.com/feeds'
                                );

        /**
         * Class constructor
         * @param   mixed  $properties  Either and associative array or another
         *                              object to set the initial properties of the object.
         */
        public function __construct($properties = null){
            if ($properties !== null)
            {
                $this->setProperties($properties);
            }

            $this->data = new stdClass();
            $this->getClient();
        }
        /**
         * Get Google_Client object
         * @return mixed Google_Client object if client ID and application_name are set OR null
         */
        public function getClient(){
            if(empty($this->client) AND $this->get('client_id') AND $this->get('aplication_name')){

                $this->client = new Google_Client();
                $this->client->setApplicationName($this->get('aplication_name'));
                $this->client->setClientId($this->get('client_id'));
            }
            return $this->client;
        }
        /**
         * Get Service AccessToken
         * @return AccessToken
         */
        public function getToken()
        {
            $key = file_get_contents($this->get('key_file_location'));
            $cred = new Google_Auth_AssertionCredentials(
                    $this->service_account_name,
                    $this->get('scopes', array()),
                    $key
            );

            $this->client->setAssertionCredentials($cred);


            if($this->client->getAuth()->isAccessTokenExpired()) {
                $this->client->getAuth()->refreshTokenWithAssertion($cred);
            }

            $service_token = json_decode($this->client->getAccessToken());
            return $service_token->access_token;
        }

        /**
         * Get Available Spreadsheets
         */
        public function getSpreadsheetsList()
        {

            $accessToken        = $this->getToken();
            $serviceRequest     = new DefaultServiceRequest($accessToken);
            ServiceRequestFactory::setInstance($serviceRequest);


            $spreadsheetService = new SpreadsheetService();
            $spreadsheetFeed    = $spreadsheetService->getSpreadsheets();

            echo '<pre>'; print_r($spreadsheetFeed);

            foreach($spreadsheetFeed as $item) {
                $spreadsheets[basename($item->getId())] = $item->getTitle();
            }

            $this->data->spreadsheets = isset($spreadsheets) ? $spreadsheets : false;
        }
        /**
         * Insert new file.
         *
         * @param string $title Title of the file to insert, including the extension.
         * @param string $description Description of the file to insert.
         * @param string $parentId Parent folder's ID.
         * @param string $mimeType MIME type of the file to insert.
         * @param string $filename Filename of the file to insert.
         * @return Google_DriveFile The file that was inserted. NULL is returned if an API error occurred.
         */
        public function insertFile($title, $description, $mimeType='application/vnd.google-apps.spreadsheet', $filename=null, $parentId=null) {
            //Google_DriveService $service Drive API service instance.
            $service = new Google_Service_Drive($this->getClient());

            $file = new Google_Service_Drive_DriveFile();
            $file->setTitle($title);
            $file->setDescription($description);
            $file->setMimeType($mimeType);

            // Set the parent folder.
            if ($parentId != null) {
                $parent = new Google_ParentReference();
                $parent->setId($parentId);
                $file->setParents(array($parent));
            }

            try {
                if(!empty($filename)){
                    $data = file_get_contents($filename);
                }else{
                    $data = '';
                }

                $createdFile = $service->files->insert($file, array(
                        'data' => $data,
                        'mimeType' => $mimeType,
                ));

                // Uncomment the following line to print the File ID
                // print 'File ID: %s' % $createdFile->getId();

                return $createdFile;
            } catch (Exception $e) {
                $this->setError($e->getMessage());
                print "An error occurred: " . $e->getMessage();
            }
        }

        /**
         * Sets a default value if not alreay assigned
         * @param   string  $property  The name of the property.
         * @param   mixed   $default   The default value.
         * @return  mixed
         */
        public function def($property, $default = null)
        {
            $value = $this->get($property, $default);
            return $this->set($property, $value);
        }

        /**
         * Returns a property of the object or the default value if the property is not set.
         * @param   string  $property  The name of the property.
         * @param   mixed   $default   The default value.
         * @return  mixed    The value of the property.
         */
        public function get($property, $default = null)
        {
            if (isset($this->$property))
            {
                return $this->$property;
            }
            return $default;
        }

        /**
         * Returns an associative array of object properties.
         * @param   boolean  $public  If true, returns only the public properties.
         * @return  array
         */
        public function getProperties($public = true)
        {
            $vars = get_object_vars($this);
            if ($public)
            {
                foreach ($vars as $key => $value)
                {
                    if ('_' == substr($key, 0, 1))
                    {
                        unset($vars[$key]);
                    }
                }
            }
            return $vars;
        }

        /**
         * Get the most recent error message.
         * @param   integer  $i         Option error index.
         * @param   boolean  $toString  Indicates if JError objects should return their error message.
         * @return  string   Error message
         */
        public function getError($i = null, $toString = true)
        {
            // Find the error
            if ($i === null)
            {
                // Default, return the last message
                $error = end($this->_errors);
            }
            elseif (!array_key_exists($i, $this->_errors))
            {
                // If $i has been specified but does not exist, return false
                return false;
            }
            else
            {
                $error = $this->_errors[$i];
            }

            // Check if only the string is requested
            if ($error instanceof Exception && $toString)
            {
                return (string) $error;
            }

            return $error;
        }

        /**
         * Return all errors, if any.
         * @return  array  Array of error messages or JErrors.
         */
        public function getErrors()
        {
            return $this->_errors;
        }

        /**
         * Modifies a property of the object, creating it if it does not already exist.
         * @param   string  $property  The name of the property.
         * @param   mixed   $value     The value of the property to set.
         * @return  mixed  Previous value of the property.
         */
        public function set($property, $value = null)
        {
            $previous = isset($this->$property) ? $this->$property : null;
            $this->$property = $value;
            return $previous;
        }

        /**
         * Set the object properties based on a named array/hash.
         * @param   mixed  $properties  Either an associative array or another object.
         * @return  boolean
         */
        public function setProperties($properties)
        {
            if (is_array($properties) || is_object($properties))
            {
                foreach ((array) $properties as $k => $v)
                {
                    // Use the set function which might be overridden.
                    $this->set($k, $v);
                }
                return true;
            }

            return false;
        }

        /**
         * Add an error message.
         * @param   string  $error  Error message.
         * @return  void
         */
        public function setError($error)
        {
            array_push($this->_errors, $error);
        }
    }

    $opt = array();
    $opt['key_file_location']   = realpath(dirname(__FILE__)).'/key_ss.p12';
    $opt['client_id']           = '*********.apps.googleusercontent.com';
    $opt['service_account_name']= '*********@developer.gserviceaccount.com';
    $opt['aplication_name']     = 'MY APPLICATION NAME';
    $GoogleSS = new GoogleSpreadSheet($opt);
    $GoogleSS->insertFile('test', 'description');
    $GoogleSS->getSpreadsheetsList();

我还有 /google-api-php-client/autoload.php 的修改版本:

<?php
    function google_api_php_client_autoload($className) {
      $classPath = explode('_', $className);
      if ($classPath[0] != 'Google') {
        return;
      }
      if (count($classPath) > 3) {
        // Maximum class file path depth in this project is 3.
        $classPath = array_slice($classPath, 0, 3);
      }
      $filePath = dirname(__FILE__) . '/src/' . implode('/', $classPath) . '.php';
      if (file_exists($filePath)) {
        require_once($filePath);
      }
    }
    function google_spreadsheet_api_php_client_autoload($className) {

        $classPath = explode('\\', $className);
        if (count($classPath) == 1) {
            $filePath = dirname(__FILE__) . '/src/Google/Spreadsheet/' .  $className . '.php';
        }else{
            $filePath = dirname(__FILE__) . '/src/' .  implode('/', $classPath) . '.php';
        } 

        if (file_exists($filePath)) {
            require_once($filePath);
        }
    }

    spl_autoload_register('google_api_php_client_autoload');
    spl_autoload_register('google_spreadsheet_api_php_client_autoload');

当我执行代码时,我得到:

Notice: Undefined index: uploadType in /var/www/google-api-php-client/src/Google/Service/Resource.php on line 175

Notice: Undefined index: uploadType in /var/www/google-api-php-client/src/Google/Service/Resource.php on line 175
An error occurred: Error calling POST https://www.googleapis.com/drive/v2/files: (401) Login Required
Google\Spreadsheet\SpreadsheetFeed Object
( .... )

为了重现该问题,您还需要下载php-google-电子表格-客户端 https://github.com/asimlqt/php-google-spreadsheet-client并将 Spreadsheet 目录上传到 /google-api-php-client/src/Google/

我已尽力提供尽可能多的详细信息,但如果有不清楚的地方,请告诉我。


我认为您的问题是访问令牌,如下所示: setAccessToken($accessToken) ,检查您的凭据。

我还添加了谷歌驱动器上传脚本。我正在使用这个脚本。

Regards.

<?php

/*******************************************************************************
 * file:        google_drive_upload.php
 * author:      ben servoz
 * description: script to upload files to Google Drive
 * notes:       instructions at http://ben.akrin.com/?p=2080
*******************************************************************************/

// configuration
//   google oauth
$client_id = "your client ID here" ;
$client_secret = "your client secret here" ;
$refresh_token = "your refresh token here" ;
//   chunk size (this HAS to be a multiple of 256KB so only change the last integer)
$chunk_size = 256 * 1024 * 400 ; // this will upload files 100MB at a time
//   miscellaneous
$verbose = true ;   
$file_binary = "/usr/bin/file" ; // used for detecting mime type
//   md5
$check_md5_after_upload = true ;
$md5sum_binary = "/usr/bin/md5sum" ;


// todo: grant URL follow thingy if it hasn't been done already

if( count($argv)<2 || count($argv)>3 || in_array("-h", $argv) || in_array("--help", $argv) ) {
    echo "usage: {$argv[0]} <file_name> [folder_id]\n\n    where <file_name> is the full path to the file that you want to upload to Google Drive.\n      and [folder_id] is the the folder where you want to upload the file (optional, defaults to root)\n\n" ;
    exit( 1 ) ;
}

$file_name = $argv[1] ;
if( !file_exists($file_name) ) {
    echo "ERROR: {$file_name} is not found on the filesystem\n" ;
    exit( 1 ) ;
}

$mime_type = get_mime_type( $file_name ) ;
if( $verbose ) { echo " > mime type detected: {$mime_type}\n" ; }

$folder_id = "" ;
if( count($argv)>2 ) {
    $folder_id = $argv[2] ;
}

// retrieving current access token
$access_token = get_access_token() ;

// we create the file that we will be uploading to with google
if( $verbose ) { echo "> creating file with Google\n" ; }
$location = create_google_file( $file_name ) ;

$file_size = filesize( $file_name ) ;
if( $verbose ) { echo "> uploading {$file_name} to {$location}\n" ; }
if( $verbose ) { echo ">   file size: " . (string)($file_size / pow(1024, 2)) . "MB\n" ; }
if( $verbose ) { echo ">   chunk size: " . (string)($chunk_size / pow(1024, 2)) . "MB\n\n" ; }

$last_response_code = false ;
$final_output = null ;
$last_range = false ;
$transaction_counter = 0 ;
$average_upload_speed = 0 ;
$do_exponential_backoff = false ;
$exponential_backoff_counter = 0 ;
while( $last_response_code===false || $last_response_code=='308' ) {
    $transaction_counter++ ;
    if( $verbose ) { echo "> request {$transaction_counter}\n" ; }

    if( $do_exponential_backoff ) {
        $sleep_for = pow( 2, $exponential_backoff_counter ) ;
        if( $verbose ) { echo ">    exponential backoff kicked in, sleeping for {$sleep_for} and a bit\n" ; }
        sleep( $sleep_for ) ;
        usleep( rand(0, 1000) ) ;
        $exponential_backoff_counter++ ;
        if( $exponential_backoff_counter>5 ) {
            // we've waited too long as per Google's instructions
            echo "ERROR: reached time limit of exponential backoff\n" ;
            exit( 1 ) ;
        }
    }

    // determining what range is next
    $range_start = 0 ;
    $range_end = min( $chunk_size, $file_size - 1 ) ;
    if( $last_range!==false ) {
        $last_range = explode( '-', $last_range ) ;
        $range_start = (int)$last_range[1] + 1 ;
        $range_end = min( $range_start + $chunk_size, $file_size - 1 ) ;
    }
    if( $verbose ) { echo ">   range {$range_start}-{$range_end}/{$file_size}\n" ; }

    $ch = curl_init() ;
    curl_setopt( $ch, CURLOPT_URL, "{$location}" ) ;
    curl_setopt( $ch, CURLOPT_PORT , 443 ) ;
    curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "PUT" ) ;
    curl_setopt( $ch, CURLOPT_BINARYTRANSFER, 1 ) ;
    // grabbing the data to send
    $to_send = file_get_contents( $file_name, false, NULL, $range_start, ($range_end - $range_start + 1) ) ;
    curl_setopt( $ch, CURLOPT_POSTFIELDS, $to_send ) ;
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1) ;
    curl_setopt( $ch, CURLOPT_HEADER, true ) ;
    curl_setopt( $ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer {$access_token}",
                                                "Content-Length: " . (string)($range_end - $range_start + 1),
                                                "Content-Type: {$mime_type}",
                                                "Content-Range: bytes {$range_start}-{$range_end}/{$file_size}") ) ;
    $response = parse_response( curl_exec($ch) ) ;
    $post_transaction_info = curl_getinfo( $ch ) ;
    curl_close( $ch ) ;

    $do_exponential_backoff = false ;
    if( isset($response['code']) ) {
        // checking for expired credentials
        if( $response['code']=="401" ) { // todo: make sure that we also got an invalid credential response
            if( $verbose ) { echo ">   access token expired, getting a new one\n" ; }
            $access_token = get_access_token( true ) ;
            $last_response_code = false ;
        } else if( $response['code']=="308" ) {
            $last_response_code = $response['code'] ;
            $last_range = $response['headers']['range'] ;
            // todo: verify x-range-md5 header to be sure, although I can't seem to find what x-range-md5 is a hash of exactly...
            $exponential_backoff_counter = 0 ;
        } else if( $response['code']=="503" ) { // Google's letting us know we should retry
            $do_exponential_backoff = true ;
            $last_response_code = false ;
        } else if( $response['code']=="200" ) { // we are done!
            $last_response_code = $response['code'] ;
            $final_output = $response ;
        } else {
            echo "ERROR: I have no idea what to do so here's a variable dump & have fun figuring it out.\n" ;
            echo "post_transaction_info\n" ;
            print_r( $post_transaction_info ) ;
            echo "response\n" ;
            print_r( $response ) ;
            exit( 1 ) ;
        }

        $average_upload_speed += (int)$post_transaction_info['speed_upload'] ;
        if( $verbose ) { echo ">   uploaded {$post_transaction_info['size_upload']}B\n" ; }

    } else {
        $do_exponential_backoff = true ;
        $last_response_code = false ;
    }
}

if( $last_response_code!="200" ) {
    echo "ERROR: there's no way we should reach this point\n" ;
    exit( 1 ) ;
}
if( $verbose ) { echo "\n> all done!\n" ; }
$average_upload_speed /= $transaction_counter ;
if( $verbose ) { echo "\n> average upload speed: " . (string)($average_upload_speed / pow(1024, 2)) . "MB/s\n" ; }

$final_output =json_decode( $final_output['body'] ) ;

if( $check_md5_after_upload ) {
    if( $verbose ) { echo "> md5 hash verification " ; }
    $result = exec( "{$md5sum_binary} {$file_name}" ) ;
    $result = trim( $result ) ;
    $result = explode( " ", $result ) ;
    $result = $result[0] ;
    if( $result!=$final_output->md5Checksum ) {
        if( $verbose ) { echo "FAIL\n" ; }
        echo "ERROR: md5 mismatch; local:{$result}, google:{$final_output->md5Checksum}\n" ;
        exit( 1 ) ;
    } else {
        if( $verbose ) { echo "OK\n" ; }
    }
}

echo $final_output->selfLink, "\n" ;

// we made it
exit( 0 )  ;


function get_mime_type( $file_name ) {
    global $file_binary ;

    $result = exec( "{$file_binary} -i -b {$file_name}" ) ;
    $result = trim( $result ) ;
    $result = explode( ";", $result ) ;
    $result = $result[0] ;

    return $result ;
}


function parse_response( $raw_data ) {
    $parsed_response = array( 'code'=>-1, 'headers'=>array(), 'body'=>"" ) ;

    $raw_data = explode( "\r\n", $raw_data ) ;

    $parsed_response['code'] = explode( " ", $raw_data[0] ) ;
    $parsed_response['code'] = $parsed_response['code'][1] ;

    for( $i=1 ; $i<count($raw_data) ; $i++ ) {
        $raw_datum = $raw_data[$i] ;

        $raw_datum = trim( $raw_datum ) ;
        if( $raw_datum!="" ) {
            if( substr_count($raw_datum, ':')>=1 ) {
                $raw_datum = explode( ':', $raw_datum, 2 ) ;
                $parsed_response['headers'][strtolower($raw_datum[0])] = trim( $raw_datum[1] ) ;
            }  else {
                echo "ERROR: we're in the headers section of parsing an HTTP section and no colon was found for line: {$raw_datum}\n" ;
                exit( 1 ) ;
            }
        } else {
            // we've moved to the body section
            if( ($i+1)<count($raw_data) ) {
                for( $j=($i+1) ; $j<count($raw_data) ; $j++ ) {
                    $parsed_response['body'] .= $raw_data[$j] . "\n" ;
                }
            }

            // we don't need to continue the $i loop
            break ;
        }
    }

    return $parsed_response ;
}


function get_access_token( $force_refresh=false ) {
    global $client_id, $client_secret, $refresh_token, $verbose ;

    if( $verbose ) { echo "> retrieving access token\n" ; }

    $token_filename = "/tmp/access_token_" . md5( $client_id . $client_secret . $refresh_token ) ;
    $access_token = "" ;
    if( !file_exists($token_filename) || $force_refresh===true ) {
        // no previous access token, let's get one
        if( $verbose ) { echo ">   getting new one\n" ; }

        $ch = curl_init() ;
        curl_setopt( $ch, CURLOPT_URL, "https://accounts.google.com/o/oauth2/token" ) ;
        curl_setopt( $ch, CURLOPT_PORT , 443 ) ;
        curl_setopt( $ch, CURLOPT_POST, 1 ) ;
        curl_setopt( $ch, CURLOPT_POSTFIELDS, "client_id={$client_id}&client_secret={$client_secret}&refresh_token={$refresh_token}&grant_type=refresh_token" ) ;
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ) ;
        curl_setopt( $ch, CURLOPT_HEADER, true ) ;
        curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded') ) ;

        $response = curl_exec( $ch ) ;
        $response = parse_response( $response ) ;

        // todo: make sure that we got a valid response before retrieving the access token from it

        $access_token = json_decode( $response['body'] ) ;
        $access_token = $access_token->access_token ;
        file_put_contents( $token_filename, $access_token ) ;
    } else {
        // we already have something cached, with some luck it's still valid
        $access_token = file_get_contents( $token_filename ) ;
        if( $verbose ) { echo ">   from cache\n" ; }
    }

    if( $access_token=="" ) {
        echo "ERROR: problems getting an access token\n" ;
        exit( 1 ) ;
    }

    return  $access_token ;
}


function create_google_file ( $file_name ) {
    global $access_token, $folder_id, $mime_type ;

    // todo: make mimeType universal
    if( $folder_id=="" ) {
        $post_fields = "{\"title\":\"{$file_name}\",
                         \"mimeType\":\"{$mime_type}\"}" ;
    } else {
        $post_fields = "{\"title\":\"{$file_name}\",
                         \"mimeType\":\"{$mime_type}\",
                         \"parents\": [{\"kind\":\"drive#fileLink\",\"id\":\"{$folder_id}\"}]}" ;
    }

    $ch = curl_init() ;
    curl_setopt( $ch, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable" ) ;
    curl_setopt( $ch, CURLOPT_PORT , 443 ) ;
    curl_setopt( $ch, CURLOPT_POST, 1 ) ;
    curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_fields ) ;
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ) ;
    curl_setopt( $ch, CURLOPT_HEADER, true ) ;
    curl_setopt( $ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer {$access_token}",
                                                "Content-Length: " . strlen($post_fields),
                                                "X-Upload-Content-Type: {$mime_type}",
                                                "X-Upload-Content-Length: " . filesize($file_name), 
                                                "Content-Type: application/json; charset=UTF-8") ) ;
    $response = curl_exec( $ch ) ;
    $response = parse_response( $response ) ;

    // access token expired, let's get a new one and try again
    if( $response['code']=="401" ) { // todo: make sure that we also got an invalid credential response
        $access_token = get_access_token( true ) ;
        return create_google_file( $file_name ) ; // todo: implement recursion depth limit so we don't rescurse to hell
    }

    // error checking
    if( $response['code']!="200" ) {
        echo "ERROR: could not create resumable file\n" ;
        print_r( $response ) ;
        exit( 1 ) ;
    }
    if( !isset($response['headers']['location']) ) {
        echo "ERROR: not location header gotten back\n" ;
        print_r( $response ) ;
        exit( 1 ) ;
    }

    return $response['headers']['location'] ;
}

?>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 PHP 中的服务帐户将文件上传到 Google Drive? 的相关文章

  • 点击 %40 变为 %2540

    当单击包含 符号的链接时 该网址给我 40 这就是我想要的 但是一旦我点击它 一秒钟后它就在我点击后变成了 2540 单击是在电子邮件内 然后定向到网站 其中 40 更改为 2540 我怎样才能让它停止变化 它现在得到这样的参数 email
  • Readfile 从大文件中读取 0 字节?

    我正在尝试通过以下方式发送一个大文件readfile 但是 没有任何内容发送到浏览器 并且readfile 回报0 not false 我尝试发送的文件大小为 4GiB 并且可由 PHP 读取 我正在设置set time limit 0 以
  • Laravel Auth:attempt() 不会持久登录

    我在网上找到了许多有类似问题的资源 但似乎没有一个解决方案可以解决我的问题 当我使用以下代码登录用户时 一切看起来都很好 email Input get email password Input get password if Auth a
  • 是否有用于绘制图表的Python API(使用线条连接两个列表之间的相应值)[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Given two lists which contain same elements of strin
  • 简单的 PHP 回显代码不起作用

    这是我的 html 和 php 脚本 h1 Bob s Auto Parts h1 table width 100 tr tr table 为什么这个输出会出现一个 gt 我希望它是 这有效 仅有的 这是输出 鲍勃的汽车零件 鲍勃
  • 如何让Apache服务index.php而不是index.html?

    如果我将以下行放入index html文件 使 Apache 包含index php file 参观index html页面向我显示了这个 这是为什么 为什么它实际上不包含 PHP 文件 正如其他人指出的那样 您很可能没有 html设置为处
  • php源代码到PO文件生成器

    我必须将我的所有回显 打印字符串转换为PHP源代码代码文件到PO file 为了语言翻译 有批次吗对流器可用于相同的 我如何做到这一点 make gettext在您的服务器上运行 setup a 翻译适配器 例如带有 gettext 适配器
  • 使用 ImageMagick 和 PHP 将 PNG 转换为 JPG 并将透明背景设置为白色

    将图像从 PNG 转换为 JPEG 时 如何使用 ImageMagick 带有 php 扩展 将透明背景设置为白色 在撰写本文时 您尚未指定正在使用哪个扩展 但如果您使用命令行 则命令将是 convert image png backgro
  • 如何关闭未关闭的 HTML 标签?

    每当我们从数据库或类似来源获取一些经过编辑的用户输入内容时 我们可能会检索仅包含开始标记但不包含结束标记的部分 这可能会妨碍网站当前的布局 有客户端或服务器端的方法来解决这个问题吗 找到了一个很好的答案 使用 PHP 5 并使用 DOMDo
  • 未传递“client_reference_id”参数

    我使用 Stripe Checkout Stripe 版本 2016 07 06 我想通过参数 client reference id 恢复个性化数据 但在 JSON 中 当我有金额或电子邮件时 我找不到它 我是在测试环境中 你能帮我吗 先
  • 编辑 HTACCESS 文件以防止直接访问特定文件夹中的特定文件

    我试图阻止直接访问子文件夹中的特定文件 我意识到这个论坛上有很多描述类似问题的主题 但是 我的似乎有点尴尬 由于我已经存在 HTACCESS 文件 这是文件的文件路径 www example com PRINCIPAL PROJECTS m
  • 如何防止在 PHP 中使用超出“使用”范围的特征方法

    我想知道是否有任何方法可以防止在 PHP 的任何类上下文之外使用特征方法 让我用一个简短的例子来解释我想要什么 这是我当前的代码 File MyFunctions php trait MyFunctions function hello w
  • 获取字符串中的最后一个整数

    我需要隔离包含多个整数的字符串中最新出现的整数 我怎样才能得到23代替1 for lastnum1 text 1 out of 23 lastnum1 this gt getEval eregi replace out of text 你可
  • 访问sendBeacon发送的数据

    文档表明sendBeacon通过发送其数据HTTP POST request 但在 PHP 中 POST变量似乎是一个空数组 这是我的 JavaScript 代码 navigator sendBeacon beacon log php My
  • WordPress 包含 SVG 文件错误

    我使用 PHP 和 WordPress 在本地主机上 我可以毫无问题地包含 SVG 文件 但在实时服务器上 我尝试包含一个 SVG 文件以便能够使用 CSS 对其进行样式设置 我收到此错误消息 Parse error syntax erro
  • Mysqli 更新抛出 Call to a member function bind_param() 错误[重复]

    这个问题在这里已经有答案了 我有一个 70 80 字段表单 需要插入到表中 因此我首先根据表单中的输入名称在数据库中创建了一个表 而不是手动创建一个巨大的插入语句 这是我使用的代码创建 更改表 function createTable ar
  • PHP 扩展开发入门 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 请推荐有关 PHP 低 级 modules 编程接口的帮助文章或教程 搜索我的书签 我发现的唯一链接是
  • PHP print_r() 中 _r 的含义是什么?

    我见过这个答案 https stackoverflow com questions 13103410 what does r suffix mean就这样 但我不确定它对于 PHP 是否相同 如果是 可重入的含义是什么 From PHP n
  • phpActiveRecord 日期时间格式不正确

    当尝试使用 phpActiveRecord 在表中创建记录时 出现以下错误 Invalid datetime format 1292 Incorrect datetime value 2013 06 20 11 59 08 PDT for
  • ZF3/2 - 如何捕获 EVENT_DISPATCH 侦听器中引发的异常?

    有什么方法可以在 EVENT DISPATCH 监听器中抛出异常吗 class Module public function onBootstrap EventInterface event application event gt get

随机推荐

  • Google Data studio 中的 COUNTIFS 函数

    我有两列 分别称为大陆和完成度 我想根据以下数据计算每个大陆的完成百分比 这是在 Excel 中使用 COUNTIFS 函数定义的 我们可以在数据工作室中实现这一目标吗 完成百分比公式为 已关闭 状态总数 状态总数 状态值为 开放 进行中
  • 迭代时从映射中删除键/值

    我正在创建这样的地图 def myMap 映射基本上是一个键的对象和一个值的整数 当我迭代地图时 我会计算该值 如果它是 0 我会将其删除 我已经尝试过了myMap remove 但我得到了ConcurrentModificationErr
  • 未知文件类型 MIME?

    如果上传的文件没有扩展名 是否必须指定 MIME 类型 换句话说 是否有默认的通用 MIME 类型 您可以使用application octet stream对于未知类型 RFC 2046 http www rfc editor org r
  • 如何忽略带有特定注释的方法的 checkstyle javadoc 警告

    当我有一个没有 javadoc 的公共方法时 Checkstyle 会发出警告 这很好 当我重写公共方法时 我没有收到警告 因为 javadoc 已在该方法的父类中可用 例如 现在我的方法有另一个注释 MyEvent 现在我确实收到了警告
  • 根据两个数字之间的差异多次插入图像。 PHP

    编写一个脚本 计算从 API 检索到的日期之间的差异 我希望它在图像中放入与差异一样多的次数 d1 new DateTime 2012 04 04 d2 new DateTime 2012 03 31 interval d1 gt diff
  • 为什么 null 需要在这里进行显式类型转换? [复制]

    这个问题在这里已经有答案了 以下代码无法编译 int a int b int a 0 a null 为了编译 需要改为 int b a 0 a int null 既然两者b null and b a是合法的 这对我来说没有意义 为什么我们必
  • 在运行剩余的 javascript 之前检查有效的电子邮件

    我有一个文本框 要求用户在其中插入有效的电子邮件地址 当用户提交有效的电子邮件地址时 会在回发数据时出现加载图形 下面的代码可以很好地显示加载图形 但它不会首先检查电子邮件地址是否有效 有人可以帮忙吗 btnEmail1Submit liv
  • Ansible 查找模块不排除搜索中的文件夹

    这是我尝试找到的剧本test juli jar under app但是 我希望排除目录 app Patchbackup从搜索到的文件夹 以下是我的剧本 tasks name Find test home directories under
  • 实体框架查询很慢,但 SqlQuery 中的相同 SQL 很快

    我看到一些非常奇怪的性能 与使用 Entity Framework Code First 和 NET Framework 版本 4 的非常简单的查询相关 LINQ2Entities 查询如下所示 context MyTables Where
  • 在 Bison 中为 && 和 || 启动短路规则运营

    我正在使用 C C 在 Bison 和 Flex 中编写一个简单的计算器 逻辑在 Bison 中完成 C C 部分负责数据结构 例如 STL 等 我有以下问题 在我的计算器中美元符号 表示 i 和 i 前缀和后缀 例如 int y 3 gt
  • 导出 libGDX 小程序时 AppletLoader 的 ClassNotFound

    我尝试以下this http www thesecretpie com 2011 05 being like minecraft or how to run your html将我的 libGDX 游戏导出为 Java 小程序 该指南有点令
  • 用于手机号码验证的正则表达式

    我想要一个用于手机号码验证的正则表达式 正则表达式模式应该是这样的 它必须接受 仅在开头和空格 或 只应允许在国家 地区代码之后 仅一次 国家 地区代码后只能允许使用 10 位数字 国家 地区代码应该是可选的 如果国家代码不存在 则仅接受
  • 放大和有角度的安全关注 - Cognito

    我试图弄清楚 Cognito 是否需要放大才能与前端一起使用 或者是否有更安全的设置方法 我问的原因是因为我有一个解决方案 允许我使用 cognito amplify 和 Angular 登录我的应用程序 但为了使其正常工作 我必须将 us
  • 如何在android中以编程方式授予“绘制其他应用程序”权限?

    我如何以编程方式授予权限Settings gt Apps gt Draw over other apps在安卓中 我想使用系统警报窗口 但无法在 Android Marshmallow 中使用 除非强制用户先通过 设置 应用程序并授予权限
  • Google Guava isNullOrEmpty 对于集合

    我看到 Guava 有 isNullOrEmpty 字符串实用方法 Strings isNullOrEmpty str 我们有类似的列表吗 就像是 Lists isNullOrEmpty list 这应该相当于 list null list
  • 使用python glob查找一个14位数字的文件夹

    我有一个文件夹 其中的子文件夹全部采用 YYYYMMDDHHMMSS 时间戳 模式 我想使用 glob 仅选择与该模式匹配的文件夹 Since glob http docs python org library glob html不支持正则
  • 为什么 UIProgressview 进度条不能调整大小?

    来自巴伐利亚的问题UIProgressViews 在这里 https stackoverflow com questions 7980891 uiprogressview and custom track and progress imag
  • 在控制台中测试路由

    我必须做什么才能在控制台中工作 假设song显然已定义 edit song id gt song id 您可以访问app您可以使用它来测试路由的对象 gt gt app root url gt http www example com gt
  • LibreOffice 宏总是显示#NULL!重新打开文件后

    我在 LibreOffice Calc 中编写了一个宏 它能够正确运行 但如果我关闭文件并重新打开 它总是显示 NULL 而不是正确的值 我在这里缺少什么 我的宏代码 Rem Attribute VBA ModuleType VBAModu
  • 如何使用 PHP 中的服务帐户将文件上传到 Google Drive?

    快速入门 在 PHP 中运行云端硬盘应用程序 https developers google com drive web quickstart quickstart php似乎使用的是过时版本的 google api php client