diff --git a/datasette/app.py b/datasette/app.py index da62934e..5b50294f 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -1303,3 +1303,11 @@ class Urls: def query(self, database, query): return "{}/{}".format(self.database(database), urllib.parse.quote_plus(query)) + + def row(self, database, table, row_path): + return "{}/{}".format(self.table(database, table), row_path) + + def row_blob(self, database, table, row_path, column): + return self.table(database, table) + "/-/blob/{}/{}.blob".format( + row_path, urllib.parse.quote_plus(column) + ) diff --git a/datasette/static/app.css b/datasette/static/app.css index 9b699a9d..f7b35516 100644 --- a/datasette/static/app.css +++ b/datasette/static/app.css @@ -457,6 +457,17 @@ svg.dropdown-menu-icon { top: 1px; } +.blob-download { + display: block; + white-space: nowrap; + padding-right: 20px; + position: relative; + background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ij48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQ3IDEwLjc4YS43NS43NSAwIDAwMS4wNiAwbDMuNzUtMy43NWEuNzUuNzUgMCAwMC0xLjA2LTEuMDZMOC43NSA4LjQ0VjEuNzVhLjc1Ljc1IDAgMDAtMS41IDB2Ni42OUw0Ljc4IDUuOTdhLjc1Ljc1IDAgMDAtMS4wNiAxLjA2bDMuNzUgMy43NXpNMy43NSAxM2EuNzUuNzUgMCAwMDAgMS41aDguNWEuNzUuNzUgMCAwMDAtMS41aC04LjV6Ij48L3BhdGg+PC9zdmc+"); + background-size: 16px 16px; + background-position: right; + background-repeat: no-repeat; +} + .anim-scale-in { animation-name: scale-in; animation-duration: 0.15s; diff --git a/datasette/views/table.py b/datasette/views/table.py index b8c9ba55..717341ae 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -167,8 +167,15 @@ class RowTableShared(DataView): display_value = plugin_display_value elif isinstance(value, bytes): display_value = jinja2.Markup( - "<Binary data: {} byte{}>".format( - len(value), "" if len(value) == 1 else "s" + '<Binary: {} byte{}>'.format( + self.ds.urls.row_blob( + database, + table, + path_from_row_pks(row, pks, not pks), + column, + ), + len(value), + "" if len(value) == 1 else "s", ) ) elif isinstance(value, dict): diff --git a/tests/test_html.py b/tests/test_html.py index 29c19844..3af9816f 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -1231,12 +1231,12 @@ def test_binary_data_display(app_client): [ '1', '1', - '<Binary\xa0data:\xa07\xa0bytes>', + '<Binary:\xa07\xa0bytes>', ], [ '2', '2', - '<Binary\xa0data:\xa07\xa0bytes>', + '<Binary:\xa07\xa0bytes>', ], ] assert expected_tds == [