Implement Etags for medias

This commit is contained in:
Romain Neutron
2012-05-23 20:01:36 +02:00
parent 7904445070
commit cefb55f4d5
4 changed files with 30 additions and 20 deletions

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\Application; namespace Alchemy\Phrasea\Application;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
/** /**
* *
@@ -28,7 +29,7 @@ return call_user_func(
$appbox = \appbox::get_instance($app['Core']); $appbox = \appbox::get_instance($app['Core']);
$session = $appbox->get_session(); $session = $appbox->get_session();
$deliver_content = function(\Session_Handler $session, \record_adapter $record, $subdef, $watermark, $stamp, $app) { $deliver_content = function(Request $request, \Session_Handler $session, \record_adapter $record, $subdef, $watermark, $stamp, $app) {
$file = $record->get_subdef($subdef); $file = $record->get_subdef($subdef);
@@ -57,7 +58,16 @@ return call_user_func(
} }
return \set_export::stream_file($pathOut, $file->get_file(), $file->get_mime(), 'attachment'); $response = \set_export::stream_file($pathOut, $file->get_file(), $file->get_mime(), 'inline');
/* @var $response \Symfony\Component\HttpFoundation\Response */
if ($file->getEtag()) {
$response->setEtag($file->getEtag());
$response->setLastModified($file->get_modification_date());
$response->isNotModified($request);
}
return $response;
}; };
$app->get('/datafiles/{sbas_id}/{record_id}/{subdef}/', function($sbas_id, $record_id, $subdef) use ($app, $session, $deliver_content) { $app->get('/datafiles/{sbas_id}/{record_id}/{subdef}/', function($sbas_id, $record_id, $subdef) use ($app, $session, $deliver_content) {
@@ -109,7 +119,7 @@ return call_user_func(
} }
} }
return $deliver_content($session, $record, $subdef, $watermark, $stamp, $app); return $deliver_content($app['request'], $session, $record, $subdef, $watermark, $stamp, $app);
})->assert('sbas_id', '\d+')->assert('record_id', '\d+'); })->assert('sbas_id', '\d+')->assert('record_id', '\d+');
@@ -165,7 +175,7 @@ return call_user_func(
} }
} }
return $deliver_content($session, $record, $subdef, $watermark, $stamp, $app); return $deliver_content($app['request'], $session, $record, $subdef, $watermark, $stamp, $app);
} else { } else {
$collection = \collection::get_from_base_id($record->get_base_id()); $collection = \collection::get_from_base_id($record->get_base_id());
switch ($collection->get_pub_wm()) { switch ($collection->get_pub_wm()) {
@@ -182,7 +192,7 @@ return call_user_func(
} }
} }
return $deliver_content($session, $record, $subdef, $watermark, $stamp, $app); return $deliver_content($app['request'], $session, $record, $subdef, $watermark, $stamp, $app);
} }
) )
->assert('sbas_id', '\d+')->assert('record_id', '\d+'); ->assert('sbas_id', '\d+')->assert('record_id', '\d+');

View File

@@ -149,10 +149,7 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
$this->record = $record; $this->record = $record;
$this->load($substitute); $this->load($substitute);
$nowtime = new DateTime('-3 days'); $this->generate_url();
$random = $record->get_modification_date() > $nowtime;
$this->generate_url($random);
return $this; return $this;
} }
@@ -349,7 +346,7 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
public function getEtag() public function getEtag()
{ {
if ( ! $this->etag && $this->is_physically_present()) { if ( ! $this->etag && $this->is_physically_present()) {
$this->setEtag(md5_file($this->get_pathfile())); $this->setEtag(md5(time() . $this->get_pathfile()));
} }
return $this->etag; return $this->etag;
@@ -364,8 +361,6 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
$stmt->execute(array(':subdef_id' => $this->subdef_id, ':etag' => $etag)); $stmt->execute(array(':subdef_id' => $this->subdef_id, ':etag' => $etag));
$stmt->closeCursor(); $stmt->closeCursor();
$this->delete_data_from_cache();
return $this; return $this;
} }
@@ -728,6 +723,7 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
$stmt->closeCursor(); $stmt->closeCursor();
$subdef = new self($record, $name); $subdef = new self($record, $name);
$subdef->delete_data_from_cache();
if ($subdef->get_permalink() instanceof media_Permalink_Adapter) { if ($subdef->get_permalink() instanceof media_Permalink_Adapter) {
$subdef->get_permalink()->delete_data_from_cache(); $subdef->get_permalink()->delete_data_from_cache();
@@ -743,7 +739,7 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
* @param boolean $random * @param boolean $random
* @return string * @return string
*/ */
protected function generate_url($random = false) protected function generate_url()
{ {
if (in_array($this->mime, array('video/mp4'))) { if (in_array($this->mime, array('video/mp4'))) {
$token = p4file::apache_tokenize($this->get_pathfile()); $token = p4file::apache_tokenize($this->get_pathfile());
@@ -756,8 +752,7 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
$this->url = "/datafiles/" . $this->record->get_sbas_id() $this->url = "/datafiles/" . $this->record->get_sbas_id()
. "/" . $this->record->get_record_id() . "/" . "/" . $this->record->get_record_id() . "/"
. $this->get_name() . "/" . $this->get_name() . "/";
. ($random ? '?' . mt_rand(10000, 99999) : '');
return; return;
} }
@@ -784,6 +779,7 @@ class media_subdef extends media_abstract implements cache_cacheableInterface
public function delete_data_from_cache($option = null) public function delete_data_from_cache($option = null)
{ {
$this->setEtag(null);
$databox = $this->get_record()->get_databox(); $databox = $this->get_record()->get_databox();
return $databox->delete_data_from_cache($this->get_cache_key($option)); return $databox->delete_data_from_cache($this->get_cache_key($option));

View File

@@ -1016,6 +1016,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface
path = :path, path = :path,
size = :size, size = :size,
substit = 1 substit = 1
updated_on = now()
WHERE name = :name AND record_id = :record_id'; WHERE name = :name AND record_id = :record_id';
$params = array( $params = array(

View File

@@ -39,7 +39,7 @@
<h5>{% trans 'upload:: Destination (collection) :' %} :</h5> <h5>{% trans 'upload:: Destination (collection) :' %} :</h5>
{# collections list #} {# collections list #}
{% if collections|length > 0 %} {% if collections|length > 0 %}
<select name="collection" class="span3" style="margin-left: 10px;"> <select name="base_id" class="span3" style="margin-left: 10px;">
{% for sbasId, availableCollections in collections %} {% for sbasId, availableCollections in collections %}
<optgroup label="{{ availableCollections['databox'].get_viewname() }}" class="select-label"> <optgroup label="{{ availableCollections['databox'].get_viewname() }}" class="select-label">
{% for collection in availableCollections['databox_collections'] %} {% for collection in availableCollections['databox_collections'] %}
@@ -55,7 +55,7 @@
<h5>{% trans 'upload:: Status :' %} :</h5> <h5>{% trans 'upload:: Status :' %} :</h5>
<table class="status-tab"> <table class="status-tab">
<tbody> <tbody>
{% for status in availableCollections['databox'].get_statusbits() %} {% for bit, status in availableCollections['databox'].get_statusbits() %}
<tr> <tr>
<td colspan="2"> <td colspan="2">
<h6>{{ status['name']|title }}</h6> <h6>{{ status['name']|title }}</h6>
@@ -67,10 +67,10 @@
<img src="{{ status['img_off'] }}" width="16" height="16" /> <img src="{{ status['img_off'] }}" width="16" height="16" />
{% endif %} {% endif %}
<span>{{ status['labeloff']|default('off') }}</span> <span>{{ status['labeloff']|default('off') }}</span>
<input type="radio" name="label_{{ collection.get_base_id() }}_{{ status['name'] }}" value="off" checked="checked"/> <input type="radio" name="status[{{ bit }}]" value="off" checked="checked"/>
</td> </td>
<td class="status-tab-right"> <td class="status-tab-right">
<input type="radio" name="label_{{ collection.get_base_id() }}_{{ status['name'] }}" value="on" /> <input type="radio" name="status[{{ bit }}]" value="on" />
<span for="labelon">{{ status['labelon']|default('on') }}</span> <span for="labelon">{{ status['labelon']|default('on') }}</span>
{% if status['img_on'] is not empty %} {% if status['img_on'] is not empty %}
<img src="{{ status['img_on'] }}" width="16" height="16" /> <img src="{{ status['img_on'] }}" width="16" height="16" />
@@ -108,7 +108,10 @@
</div> </div>
{# download box #} {# download box #}
<div class='download-box'></div> <div>
<ul class='download-box'>
</ul>
</div>
</div> </div>
</form> </form>