GithubHelp home page GithubHelp logo

aliyun-oss-support's Introduction

阿里云 OSS 支持插件 (Aliyun OSS For WordPress)

本插件主要为 Wordpress 提供基于阿里云 OSS 的远程附件存储功能,并且最大限度的依赖 Wordpress 本身功能扩展来实现,以保证插件停用或博客搬迁时可以快速切换回原来的方式。

插件特色

  1. 支持 Aliyun OSS 的图片服务(根据参数获得不同尺寸的图片)
  2. 自定义文件在 Bucket 上的存储位置
  3. 支持 Https 站点
  4. 支持阿里云内网和 VPC 网络
  5. 全格式附件支持,不仅仅是图片
  6. 支持 WordPress 4.4+ 新功能 srcset,在不同分辨率设备上加载不同大小图片
  7. 支持 WordPress 5.0+ 默认古藤堡编辑器Gutenburg
  8. 支持阿里云url鉴权,实现高级别防盗链功能,支持阿里云CDN的A、B、C所有方式鉴权,推荐A方式
  9. 支持在 WordPress 后台编辑图片
  10. 支持预设图片样式,图片保护,自定义分割符
  11. 中英文双语支持,方便使用英文为默认语言的同学
  12. 支持在其他插件/主题中通过系统钩子调用插件功能
  13. 代码遵循 PSR-4 规则编写

插件使用

关于插件使用方式的 Wiki: Quick start

下载

latest release

安装

将插件解压上传到 /wp-content/plugins/ 或者通过 WordPress 插件中心上传安装

配置

启用插件 Aliyun OSS

进入设置页面 完成相关设置

  • 如果你使用的 ECS 与 OSS 在同一区域,可以开启『内网/internal』选项,节约流量
  • 『Bucket 域名/Bucket Host』一项会自动补全,也可以手动设置为你的 自定义域名 或 CDN 域名

screenshot

启用 OSS 图片服务

阿里云 OSS 提供了根据 url 参数来获得各种尺寸的 阿里云OSS图片处理服务(Image Service,简称 IMG), 相比起 WordPress 上传的时候生成各种尺寸的图片, 这是一种更优雅的解决方案, 占用的存储空间更小, 尺寸变更更灵活。

如何开启并配置图片服务, 请参见: How to use Image Service

另外还有几点需要你了解:

  1. 开启图片服务时, 只有原图会被上传到 OSS, 缩略图本地依旧会生成但不会上传
  2. 基于第 1 条, 建议开启图片服务后就不要关了, 关掉会导致之前上传的图片缩略图无法访问(文章中的图片不受影响)
  3. 基于第 2 条, 如果你确实想关掉图片服务,参见下一项里面的解决方案

启用 CDN URL鉴权

1.阿里云URL鉴权功能由CDN服务提供,安全级别比较高,启用URL鉴权功能时,需要先在阿里云CDN控制面板-域名管理-管理-访问控制中设置鉴权方式和鉴权主/备Key,Key为完全自定义,请勿使用您的密码/AK/SK,鉴权方式推荐设置为A方式。具体设置详见什么是url防盗链

2.在阿里云控制台中设置好鉴权方式和Key之后,打开插件URL鉴权功能,填入您的鉴权方式和Key,以及您希望URL失效的时间(按小时计),即可实现URL鉴权

3.如果不希望开启URL鉴权,阿里云CDN和OSS还带有更为简单的Refer黑/白名单防盗链功能,安全性稍差且不带链接失效时间设置,详见CDN如何配置refer防盗链OSS防盗链使用指南

启用插件后,老文件无法访问

参见 WIKI:How to handle old images

关于不在本地服务器上保留文件

『不在本地服务器上保留文件』建议不要开启, 理由如下:

  1. 如果同时开启『图片服务』, 当你想停用这个插件的时候不可避免的会遇到缩略图丢失问题
  2. 如果没有同时开启『图片服务』, 当你从后台删除图片或附件时, OSS 里面的缩略图无法被删掉

题外

本插架由官方商店中 马文建(@mawenjian) 同学的「阿里云附件」插件拓展而来。由于马同学在曾经的某段时间里没能即时维护这个项目,也没有开源,于是我在修复 bug 并 rebuild 后,将这个野生的修订版发布到阿里云社区,意外获得了 ACE 社区官方管理组的推荐。

后来,马同学 release 了 2.0 版本并开源他的项目了,我就中止了这边的维护。但依旧是有网友提 Issue 或发邮件来询问,加上自己的需求,有时间的时候,也就修补一下大家反应的问题,也许还是会有人会用到。

由于插件沿用了马同学插件的名字,并 WordPress 官方不再允许在未经授权的情况下使用知名商标(如:Aliyun) 作为插件名称的一部分,所以这个插件并没有提交官方商店的计划。(重新想个名字对我来说太麻烦了~~( ̄▽ ̄))

更新日志

CHANGELOG.md

项目依赖

贡献代码

  1. Fork 这个仓库
  2. Clone 源码
  3. 执行 composer install
  4. 安装到本地 WordPress 中或者 执行 docker-compose up 启用一个新实例
  5. 完成你的修改并测试
  6. 提交一个 Pull Request

开源协议

BSD

aliyun-oss-support's People

Contributors

0xjacky avatar inoodle-git avatar liliang13 avatar mosuke5 avatar rocknhawk avatar tyt2y3 avatar xiaobaozi233 avatar yiichou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aliyun-oss-support's Issues

Aliyun OSS 插件实用扩展

有需要的拿去用。

require_once(ABSPATH . '/wp-content/plugins/aliyun-oss-support/src/Config.php');
require_once(ABSPATH . '/wp-content/plugins/aliyun-oss-support/src/UrlHelper.php');

use OSS\WP\Config;
use OSS\WP\UrlHelper;

class ImageUtility
{
    /**
     * 根据传入的相对路径,获取 OSS 路径
     * @param $url
     * @param $style
     * @param $storePath OSS 基础路径 名称,不填则采用后台配置的路径
     * @return string
     */
    public static function get_ali_image_src_by_src($url, $style, $storePath = null)
    {
        $storePath = empty($storePath) ? Config::$storePath : $storePath;
        $staticHost = Config::$staticHost;
        $u = $staticHost . $storePath . $url;
        return UrlHelper::aliImageStyle($u, $style);
    }

    /**
     * 在传入的图片 url 追加上 oss style
     * @param $url
     * @param $style
     * @return string
     */
    public static function append_ali_image_src_style($url, $style)
    {
        if (is_array($url)) $url = @$url[0];
        $index = strpos($url, "?x-oss-process=");
        $u = ($index == -1) ? $url : substr($url, 0, $index);
        return UrlHelper::aliImageStyle($u, $style);
    }

}

用法:
放到 php 里面
require_once 进来
use ImageUtility;

调用就可以了

ImageUtility::get_ali_image_src_by_src("folder1/image1.jpg","full");

OSS插件无法应用到Download Monitor插件

正常媒体库上传可以及时更改链接,但使用Download Monitor快速上传的时候只会给出本应该上传到的链接,即upload/dlm_upload/xxxxx,而非直接给出OSS的链接。。。
希望能给这个比较多人用的插件做下优化QAQ

建议不要打包aliyun-oss-wp

3.0beta里面,aliyun-oss-wp.phar不利于修改,建议还是不要打包了,比如我现在就想修改一下图片服务的参数,默认的 20w_30h_1l_1c 不是太适合我

同名文件上传时,后上传的图片的原图页面,会展示成先上传的那张图,缩略图则不受影响

此问题在未勾选“不在本地保存原图”功能时出现

操作步骤:
将两张不同的jpg图片A,B,先后命名为同一个名字然后先后上传,然后点击后上传的图片
预期:
显示为图片A
实际:
显示为图片B

继续操作:
在出错的这张图B下点“编辑图片”
预期:
展示出错的原图B
实际:
展示正确的原图A

继续操作:
在这张正确的原图A上,截取全图保存
预期:
保存为正确的原图A
实际:
保存为正确的原图A,但文件名相同的文件B,被覆盖成了A,同时 ,删除A,B任意一张图,都会导致两张图都打不开

推断:
WordPress自带的上传,能自动判断文件是否重名,并重命名文件,但上传到oss后,文件名无法判断文件是否重名,所以出现了后图覆盖前图的情况,望作者能抽空看看

然而并用不了。。

2016-08-12看到这个插件是唯一更新了aliyun-oss-php-sdk的插件,然而并用不了 OnO。。请问一下markdown文件里说的回源是什么意思呢,localhost也能使用回源吗

和EvernoteSync 插件似乎有点不协调

在使用EvernoteSync插件,把图文同步到OSS后,在wp下,图片都无法显示。

原因是,如果图片是a.jpg, 在同步后,oss上的名字是a-100x43.jpg, a-150x150.jpg, a-300x300.jpg,唯独没有a.jpg。
如果不使用OSS插件,同步后,图片可以正常显示,且在code和wp媒体的图片名是a.jpg

奇怪的是,如果使用OSS,新建文章插入图片,图片都是没有问题的,而且在OSS的名字是a.jpg。

不知道为什么使用EvernoteSync后,图片上传到OSS就被自动标记了分辨率,在阿里OSS各种设置,也没有效果。

求帮助

这个能否做到双向同步?

现在是在wordpress上传的图片会同步到阿里云oss里面去,
如果我单独上传图片到阿里云oss里面,
在wordpress网站这边显示出单独在阿里云oss上传的图片。
这样对多个网站用同个附件挺有帮助的。

不知道阿里云oss是否支持这样做?

无法配合阿里云CDN使用

域名:example.com
网站:www.example.com
OSS外网地址:somebucket.blabla.example.com
OSS绑定域名:oss.example.com
CDN加速域名:cdn.example.com -> somebucket.blabla.example.com
CNAME解析:oss.example.com -> cdn.example.com
此时本插件的的bucket域名不能改为CDN地址,否则无法访问,不修改的话,保存的图片不会被CDN加速

自己 add image size() 的名称无法被插件调用啊

自己命名的缩略图名称,插件无法传递给oss。
看了一下代码 UrlHelper.php

foreach(array('thumbnail', 'post-thumbnail', 'medium', 'medium_large', 'large', 'full') as $style ) {

这里只有WP默认的缩略图名称,
我自己在后面添加了主题注册和自己注册的名称后,才能正常使用。

请问这的确需要这么改动才能起作用吗?
还是我的设置问题吗?

上传图片会报HTTP错误,但图片能上传成功,可最终图片尺寸会丢失

错误信息如下

Warning: filesize():
stat failed for /data/home/bxu2359040325/htdocs/wp-content/uploads/2016/10/[email protected] in phar:///data/home/bxu2359040325/htdocs/wp-content/plugins/aliyun-oss-support-master/aliyun-oss-php-sdk-2.0.7.phar/src/OSS/OssClient.php on line 1310

Fatal error: Uncaught exception 'OSS\Core\OssException' with message 'The size of fileUpload cannot be determined in multiuploadFile().' in phar:///data/home/bxu2359040325/htdocs/wp-content/plugins/aliyun-oss-support-master/aliyun-oss-php-sdk-2.0.7.phar/src/OSS/OssClient.php:1317 Stack trace:
#0 /data/home/bxu2359040325/htdocs/wp-content/plugins/aliyun-oss-support-master/src/Upload.php(61): OSS\OssClient->multiuploadFile('bucket-3', 'wp-content/uplo...', '/data/home/bxu2...', Array)
#1 [internal function]: OSS\WP\Upload->uploadThumbToOss(Array)
#2 /data/home/bxu2359040325/htdocs/wp-includes/plugin.php(235): call_user_func_array(Array, Array)
#3 /data/home/bxu2359040325/htdocs/wp-includes/post.php(4891): apply_filters('wp_update_attac...', Array, 153)
#4 /data/home/bxu2359040325/htdocs/wp-admin/includes/media.php(375): wp_update_attachment_metadata(153, Array)
#5 /data/home/bxu2359040325/htdocs/wp-admin/async-upload.php(93): media_handle_upload('async-upload', 0)
#6 {main} thrown in phar:///data/home/bxu2359040325/htdocs/wp-content/plugins/aliyun-oss-support-master/aliyun-oss-php-sdk-2.0.7.phar/src/OSS/OssClient.php on line 1317

文章插入图片的完整尺寸缺少origin标

文章插入图片,尺寸选在“完整尺寸”,文章在预览时图片的srcset里没有用@!origin标

<a href="https://osspath/images/2017/01/network-interfaces.png@!origin" target="_blank"><img class="aligncenter wp-image-295 size-full" src="https://osspath/images/2017/01/network-interfaces.png@!origin" alt="OpenWrt-Network-Interface-Overview" width="971" height="861" srcset="https://osspath/images/2017/01/network-interfaces.png 971w, https://osspath/images/2017/01/network-interfaces.png?x-oss-process=style/medium 300w, https://osspath/images/2017/01/network-interfaces.png?x-oss-process=style/medium_large 768w" sizes="(max-width: 971px) 100vw, 971px"></a>

支持 WooCommerce 吗?

您好,插件无问题,可用,赞!

插件的图片服务只支持 6 种样式,能够支持WooCommerce的图片服务吗?(shop_thumbnail、shop_catalog、shop_single)

让插件更好的支持中文

您好,

因为插件不支持中文图片,因此应用之后发现部分图片无法显示出来。
在应用插件之前,网站已经上传几百于张图片,多数图片为中文命名。按照迁移流程完成图片服务器的设置之后,有部分图片显示不出来。因此进行了几天的追踪,发现为oss-support.php文件中的205行

    $filename = basename($data['file']);

php中的basename函数不支持中文所致。因此尝试进行了修复,替换为

$filename = preg_replace('/^.+[\\\\\\/]/', '', $data['file']);
//网上搜寻的用于修复basename不支持中文的修复方案

目前工作基本正常。

无法上传

AK.SK都设置好了,但是无法上传任何文件。不止图片、上传,,没有提示。
qq 20150429223528
qq 20150429223559

无法启动插件

Parse error: syntax error, unexpected '
文件末尾增加?>后提示
Parse error: syntax error, unexpected '['

实在不会搞了 特来求助

Missing argument 3 for modefiy_img_srcset_url()

On Media/Library page, following errors displayed under each image file if he file display mode is set to list.
If the display mode is set to grid, no such errors.

Env:

Wordpress version: 4.5.3 (en)

Warning: Missing argument 3 for modefiy_img_srcset_url() in
{My Site Root Url}/wp-content/plugins/aliyun-oss-support-master/oss-support.php on line 249

Warning: Missing argument 4 for modefiy_img_srcset_url() in
/{My Site Root Url}/wp-content/plugins/aliyun-oss-support-master/oss-support.php on line 249

Warning: Missing argument 5 for modefiy_img_srcset_url() in
{My Site Root Url}/wp-content/plugins/aliyun-oss-support-master/oss-support.php on line 249

原图怎么加水印?

请教一下,怎么给存在OSS的原图加水印呢?我加了4个OSS样式(medium,large,post-thumbnail,thumbnail) ,后台媒体里看到缩略图都是有水印的,但原图没有水印,原图要怎么加水印呢?原图的样式叫什么呢?

使用插件之后 网站无限加载

今天发现了插件!
点赞诶!

但是遇到点问题就是开启插件之后 设置应该没错误

然后网站就一直loading

一直loading

换过不同的bucket

关闭之后 立马打开网站

不知道为什么

还希望大大能建个群 大家一起交流呀

老文章上传图片日期路径错误

在Wordpress中,如果直接上传,它会把文件保存在本月的目录下(如/2014/12/),但是如果在文章中上传,它会把文件保存在文章发布日的目录下(如/2011/08/),使用了这个插件之后,我发现在数据库和服务器本地硬盘中的地址都是文章发布日的,而OSS上的文件会新建在本月,于是会导致读不出来这个文件,不知道这算不算一个bug。

via: sjw(at)cnsjw.cn

插件不支持buddypress。

如题,启用BuddyPress之后,不能修改头像以及背景图。可以的话,下个版本发布时可以修复一下吗?

好像失效了。。

上传文件到服务器成功,但是oss里面没有。
看上去是sdk包太旧造成的。

无法启用插件

我使用阿里云的弹性WEB托管,不能启用插件,错误如下:

无法启用插件,因为它引起了一个致命错误(fatal error)。
ERROR: manifest length read was "389051" should be "7602176"

不知道是为什么

注意目前非杭州机房以外的 oss 帐号支持不完全可行,可尝试设置 endpoint

$config = array(
    'id'     => 'xx',
    'key'    => 'xx',
    'bucket' => 'xx',
    'endpoint' => 'oss.aliyuncs.com'
);
$cache = Alibaba::Storage($config);
青岛节点外网地址: oss-cn-qingdao.aliyuncs.com 
青岛节点内网地址: oss-cn-qingdao-internal.aliyuncs.com

北京节点外网地址:oss-cn-beijing.aliyuncs.com
北京节点内网地址:oss-cn-beijing-internal.aliyuncs.com

杭州节点外网地址: oss-cn-hangzhou.aliyuncs.com
杭州节点内网地址: oss-cn-hangzhou-internal.aliyuncs.com

香港节点外网地址: oss-cn-hongkong.aliyuncs.com
香港节点内网地址: oss-cn-hongkong-internal.aliyuncs.com

深圳节点外网地址: oss-cn-shenzhen.aliyuncs.com
深圳节点内网地址: oss-cn-shenzhen-internal.aliyuncs.com

美国硅谷节点外网地址: oss-us-west-1.aliyuncs.com
美国硅谷节点内网地址: oss-us-west-1-internal.aliyuncs.com

原地址oss.aliyuncs.com 默认指向杭州节点外网地址
原内网地址oss-internal.aliyuncs.com 默认指向杭州节点内网地址

参看链接:
http://docs.aliyun.com/#/ace/sdk/php&storage
http://docs.aliyun.com/#/oss/product-documentation/domain-region

Support for JP region

Today JP region is opened. So I want to support JP region oss.
Can you support this?

解决srcset无法显示图片和安装插件后转移已有图片到OSS

修复srcset的图片显示

我当前应用的是WordPress 4.4.2版本,文章中插入的图片,如果编辑过大小,那么WordPress会使用srcset项目来根据缩放大小自动的显示图片。示例如下:

<img class="alignnone wp-image-463" src="http://img.example.com/wp/2016/03/example.jpg" alt="example" width="201"
     height="201"
     srcset="http://oss.example.com/wp/2016/03/example-150x150.jpg 150w,
            http://oss.example.com/wp/2016/03/example-300x300.jpg 300w,
            http://oss.example.com/wp/2016/03/example-768x768.jpg 768w,
            http://oss.example.com/wp/2016/03/example-1024x1024.jpg 1024w,
            http://oss.example.com/wp/2016/03/example-210x210.jpg 210w,
            http://oss.example.com/wp/2016/03/example.jpg 1280w"
     sizes="(max-width: 201px) 100vw, 201px">

此代码存在两个问题

  1. 图片链接不正确,oss.example.com是附件上传地址,无法使用OSS的图片服务。
  2. 图片文件名称不正确,使用OSS图片服务,命名应该为example.jpg@!thumbnail等。

经过研究代码后发现,此项功能并没有应用wp_get_attachment_url这项功能,而是由函数内部通过wp_calculate_image_srcset_meta_wp_upload_dir_baseurl获取链接后自行拼接。因此,为了修复这个问题,我同时修改了插件和WordPress源代码来修复这一问题。(由于本人对WordPress并不熟悉,因此修复方案并非最佳解决方案,如果有更好方案请互相交流。)

修改方案

修改PATH/wp-content/plugins/aliyun-oss-support-master/oss-support.php文件

// wp-content/plugins/aliyun-oss-support-master/oss-support.php
// 第194行起
if(!$oss_options['img_url'] == "")
    add_action('wp_delete_file', 'delete_thumb_img', 99);

改为

if(!$oss_options['img_url'] == ""){
    add_filter('wp_get_attachment_metadata', 'modefiy_img_meta', 990);
    add_filter('wp_calculate_image_srcset_meta', 'modefiy_img_meta', 990); //增加此项处理
}

修改 PATH/wp-includes/media.php文件

// wp-includes/media.php
// 第1048行起(4.4.2版本)
$image_baseurl = _wp_upload_dir_baseurl();
$image_baseurl = trailingslashit( $image_baseurl ) . $dirname;

改为

$image_baseurl = _wp_upload_dir_baseurl();

//插入如下部分,借用了插件中替换url的部分代码
$oss_options = get_option('oss_options', TRUE);
if(!$oss_options['img_url'] == ""){
    $image_baseurl = rtrim($oss_options['img_url'], '/');
    if(rtrim($oss_options['path'], '/') != ""){
        $image_baseurl = $image_baseurl .'/'. rtrim($oss_options['path'], '/');
    }
}

$image_baseurl = trailingslashit( $image_baseurl ) . $dirname;

运行效果演示(可正常的从oss中获取图片并显示出来)

<img class="alignnone wp-image-463" src="http://img.example.com/wp/2016/03/example.jpg" alt="example" width="201"
     height="201"
     srcset="http://img.example.com/wp/2016/03/example.jpg@!thumbnail 150w, 
                  http://img.example.com/wp/2016/03/example.jpg@!medium 300w, 
                  http://img.example.com/wp/2016/03/example.jpg@!medium_large 768w, 
                  http://img.example.com/wp/2016/03/example.jpg@!large 1024w, 
                  http://img.example.com/wp/2016/03/example.jpg@!medium 210w, 
                  http://img.example.com/wp/2016/03/example.jpg 1280w"
     sizes="(max-width: 201px) 100vw, 201px">

可以看到,链接被替换成img.example.com,图片名称也正确了。

另外,演示代码中的图片类型数量与原版插件支持的要多一些(如多了medium_large),如果有需要,请自行在oss-support.php文件的modefiy_img_meta函数中添加(请在阿里云OSS后台的图片处理功能中也一并添加,具体教程在插件安装说明中)。

转移已有图片到OSS并修复链接

安装好插件后,我进行了一次批量的wp-content/uploads上传到OSS服务器的文件传输。

但是,已经上传好的文章中,还是保存着本地的文件链接,修改方法只需要运行一次SQL指令即可,指令如下:

update `wp_posts` set `post_content`=REPLACE(`post_content`,'http://example.com/wp-content/uploads/','http://img.example.com/wp/');

请注意,请先备份数据库,并将上诉SQL语句中的两个链接替换成您自己的地址
http://example.com/wp-content/uploads/ - 之前数据库中保存的链接
http://img.example.com/wp/ - 阿里云OSS的图片链接

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.