23

I updated an image (from PHP) but still the old version of the image is downloaded.

If I download the image on the GCS console, I can download the new version of the image. However, this url below returns the old version.

https://storage.googleapis.com/[bucket name]/sample-image.png

It seems that the old image is on the Google's edge cache.

Some articles say that I should delete the image object then insert the new image object so that the edge cache is cleared.

Does anyone know about this?


Update 1

This is my PHP code which is on GCE.

$obj = new \Google_Service_Storage_StorageObject();
$obj->setName($path . "/" . $name);

$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(\Google_Service_Storage::DEVSTORAGE_FULL_CONTROL);

$storage = new \Google_Service_Storage($client);
$bucket = 'sample.com';

$binary = file_get_contents($_FILES['files']['tmp_name']);
$fileInfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $fileInfo->buffer($binary);

$storage->objects->insert($bucket, $obj, [
    'name' => $path . "/" . $name,
    'data' => $binary,
    'uploadType' => 'media',
    'mimeType' => $mimeType,
]);

It seems that only these parameters are valid. I don't think I can set any cache settings.

// Valid query parameters that work, but don't appear in discovery.
private $stackParameters = array(
    'alt' => array('type' => 'string', 'location' => 'query'),
    'fields' => array('type' => 'string', 'location' => 'query'),
    'trace' => array('type' => 'string', 'location' => 'query'),
    'userIp' => array('type' => 'string', 'location' => 'query'),
    'quotaUser' => array('type' => 'string', 'location' => 'query'),
    'data' => array('type' => 'string', 'location' => 'body'),
    'mimeType' => array('type' => 'string', 'location' => 'header'),
    'uploadType' => array('type' => 'string', 'location' => 'query'),
    'mediaUpload' => array('type' => 'complex', 'location' => 'query'),
    'prettyPrint' => array('type' => 'string', 'location' => 'query'),
);

https://github.com/google/google-api-php-client/blob/master/src/Google/Service/Resource.php

I tried this way but not work so far. This is for only GAE...? (Or mounting may be necessary)

$image = file_get_contents($gs_name);
$options = [ "gs" => [ "Content-Type" => "image/jpeg"]];
$ctx = stream_context_create($options);
file_put_contents("gs://<bucketname>/".$fileName, $gs_name, 0, $ctx);

How do I upload images to the Google Cloud Storage from PHP form?


Update 2

API doc shows cacheControl property of Request body. I guess that using API directly (not via SDK) is a way. I will try it.

https://cloud.google.com/storage/docs/json_api/v1/objects/insert

cacheControl    string  Cache-Control directive for the object data.    writable

I think I found it finally!

$obj->setCacheControl('no-cache');

Update 3

$bucket_name = 'my-bucket';
$file = "xxx.html";
$infotowrite = "999";
$service = new Google_Service_Storage($client);
$obj = new Google_Service_Storage_StorageObject();
$obj->setName($file);
$obj->setCacheControl('public, max-age=6000');
$results = $service->objects->insert(
        $bucket_name,
        $obj,
        ['name' => $file, 'mimeType' => 'text/html', 'data' =>   $infotowrite, 'uploadType' => 'media']
);

Set Cache-Control php client on Google Cloud Storage Object

We can check the result

gsutil ls -L gs://...
Community
  • 1
  • 1
zono
  • 8,366
  • 21
  • 75
  • 113

1 Answers1

47

By default, if an object is publicly accessible to all anonymous users and you do not otherwise specify a cacheControl setting, GCS will serve a Cache-Control header of 3600 seconds, or 1 hour. If you're getting stale object data and haven't been messing with cache control settings, I assume you're serving publicly accessible objects. I'm not sure if Google itself is caching your object data or if there's some other cache between you and Google, though.

In the future, you can fix this by explicitly setting a shorter Cache-Control header, which can be controlled on a per-object basis with the cacheControl setting.

Right now, you can probably get around this by tacking on some made up extra URL query parameter, like ?ignoreCache=1

More: https://cloud.google.com/storage/docs/xml-api/reference-headers#cachecontrol

Brandon Yarbrough
  • 37,021
  • 23
  • 116
  • 145
  • Perfect. This is what I wanted to know. Thank you so much. – zono May 12 '16 at 06:17
  • Some say that stream_context_create is a possible way. Do you think so? Google API PHP client does not allow to set cache settings. Do you know any workarounds? "?ignoreCache=1" is OK but I don't want to change my code. – zono May 12 '16 at 09:45
  • Google API PHP client does in fact allow one to set cache settings on an object: http://stackoverflow.com/questions/32228147/set-cache-control-php-client-on-google-cloud-storage-object – Brandon Yarbrough May 12 '16 at 18:06
  • 1
    Yes, Google is caching the data from buckets, too, and this cache respects the `Cache-Control` setting, so default is 1 hour. After update of a bucket object, you may get randomly old or new object until the cache expires. – xmedeko Nov 16 '17 at 12:58
  • @xmedeko why doesn't updating the bucket object automatically invalidate the cache? – Crashalot Feb 14 '20 at 08:45
  • 1
    @Crashalot that's how clouds (and CDNs) work. The caches may be spread around the world, you can never make an ideal solution. If you need immediate change, upload a new object on every change and distribute the new object URL in your app by yourself. – xmedeko Feb 14 '20 at 10:05
  • @xmedeko do you know if there is a way to force invalidate the cache for a particular object? – Crashalot Feb 14 '20 at 21:36
  • 1
    The easiest way to force-invalidate a request is to append a fake URL query parameter with a GUID value. The most canonically correct way is to include the "Cache-Control: no-cache" header directive in the request. For GCS specifically, you can disable caching for an object by setting that object's `cacheControl` property. – Brandon Yarbrough Feb 18 '20 at 05:17