mindpin / image-service Goto Github PK
View Code? Open in Web Editor NEW图床服务。提供多版本图片转换。
Home Page: http://img.4ye.me/
图床服务。提供多版本图片转换。
Home Page: http://img.4ye.me/
参考资料:
http://www.mindpin.com/mockups/img4ye/2014-4-9-v2-1/#p=structure
图片改为新的云存储后,要保证已经有的旧数据还能正确读取
所以需要给 Image 增加一个字段 is_oss,并把所有现有数据的该字段设置为 true
根据此字段来判断是否是旧数据,从而正确读取旧的图片数据
模型结构:
belongs_to :user
belongs_to :file_entity
x # 正整数
y # 正整数
text # 文本
需求 API
创建:传 x,y,text,返回 id
删除:传 id
取得所有:传图片id,返回数组,包括每一项的id,x,y,text
API 实现写在 white_board_controller 里
10月15日,img4ye 第一轮的网页版改版已经完成。目前的版本是1.0版
1.0版在原始版的基础上调整了网页视觉呈现,但没有增加什么特性。
2.0版本的计划是想把此服务由“团队内部使用”演化为“可以让更多人注册使用”
2.0版包括以下的原始需求(需细化)
可以 redis 缓存(file_entity_ids.sort.base64 -> zip_url),设置2个小时的过期时间(根据实际运营情况再去调整)
然后使用 sidekiq 的计划任务功能,设置超过2个小时后删除七牛上储存的ZIP文件
在修改 pinidea 代码的过程中,发现 pinidea 和 img4ye 的 oauth devise provider
写法上差别较大。
感觉这部分有必要做成 gem 以便复用。
0.3.1 完成后可以确定一下如何封装。需要确定哪些是写死的,哪些需要配置。
UI动态展示视频:
http://oss.aliyuncs.com/pie-documents/20141010/Untitled.mp4
补充:LOADING图标的颜色是 #666
两个大图标的图标字符分别是 "\f03e" fa-image 和 "\f030" fa-camera
其中用到了特定字体 Futura-Condensed
在这里可以获取:https://github.com/mindpin/image-service/tree/master/mobile-ui/css/fonts
关于LOGO文字颜色,img 的颜色是 #555,4ye 的颜色是 #7DB500
URL 文字大小 12dp
loading 图标文字大小 24dp
URL 背景色 #F7F7F7
0.4 版之前,0.3 版会继续进行一些更新,所有更新的版本都是 0.3.x 版。
在接下来的一段时间,需要进行以下运营工作:
每天使用产品并报告问题;
问题记录在 #28
将产品小规模推荐给一些朋友/网友,并跟踪其使用频度,使用方式,并收集其反馈;
建议可以使用 pinidea 的反馈收集表格来记录
上传一些成套的图片,并且把地址记录到本楼;
后续版本的需求研究可能会用到这些成套图片。因此现在就开始准备。成套图片可以是壁纸集,漫画,剧照,摄影集等。
例如 《二十四节气摄影集》:
http://i.teamkn.com/i/h577ZEGZ.jpg
http://i.teamkn.com/i/snFRbZSn.jpg
http://i.teamkn.com/i/aErVeo6T.jpg
http://i.teamkn.com/i/d1Z9OMUd.jpg
http://i.teamkn.com/i/WEo7nzzj.jpg
http://i.teamkn.com/i/tLGUnf2c.jpg
http://i.teamkn.com/i/SoooTdsr.jpg
http://i.teamkn.com/i/M0uXLcSH.jpg
http://i.teamkn.com/i/m7D55Sok.jpg
http://i.teamkn.com/i/Wt0PydF1.jpg
http://i.teamkn.com/i/MWklCNTX.jpg
http://i.teamkn.com/i/xf2yDdNg.jpg
http://i.teamkn.com/i/Pn7ZOWRP.jpg
http://i.teamkn.com/i/rCumre6r.jpg
http://i.teamkn.com/i/IfmVRJtl.jpg
http://i.teamkn.com/i/Wp7jDo7D.jpg
http://i.teamkn.com/i/Y6Gq0hb6.jpg
http://i.teamkn.com/i/pz5pSs0e.jpg
http://i.teamkn.com/i/hCRnUVRR.jpg
http://i.teamkn.com/i/ChjiwQ0N.jpg
http://i.teamkn.com/i/ps2hglxP.jpg
http://i.teamkn.com/i/CmmYJPUy.jpg
http://i.teamkn.com/i/xluj45eT.jpg
http://i.teamkn.com/i/uYuDjVpt.jpg
在平时的日常工作中,设法使用图片实时标注功能来辅助一些任务的沟通。
七牛文档地址: http://developer.qiniu.com/docs/v6/api/reference/fop/mkzip.html
阿里云暂时不考虑
目前 meta 数据获取存在一些小问题,等页面修改全部完成,部署时,应运行相关 rake task 处理一下所有历史图片的 meta 信息记录
目前的 CDN 域名 img.teamkn.com 较长。将来希望使用较短的域名提供图片 CDN 服务,如 i.4ye.me.
而且所有图片路径直接从根路径开始,而不是用 /i/
不过阿里云的 CDN 服务需要域名备案,而北京进行 .me 和 .fm 这样域名的备案可能不方便。
备案问题解决前暂时先搁置。
明天来看一下
注意点:
每个用户都有自己的图片尺寸配置,全局有一个匿名用户的图片配置,其实就是相当于 user_id 是 nil 的图片尺寸配置
图片尺寸配置不用考虑数据不用考虑旧数据迁移的问题,需要重新设置一个格式,为了和云存储的实现格式解耦,这个需要进一步讨论
根据
https://github.com/mindpin/image-service/wiki/Android-lib-%E8%AE%BE%E8%AE%A1
编写 Android Lib
可以稍晚些开始(等第二轮迭代时间确定),不用立即进行
使用这个img4ye JS API,可以很方便的上传图片,音频,视频到 img4ye
img4ye JS API 依赖 jQuery
<script src="/xx/jquery.min.js" />
引入 jquery 后,在后边增加
<script src="http://img.4ye.me/assets/plugins/uploader.js" />
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/xx/jquery.min.js" />
<script src="http://img.4ye.me/assets/plugins/uploader.js" />
<script>
jQuery(function(){
var options = {
// 不能为空
// 指定一个 jquery selector str 或者 dom 或者 jQuery(dom),必须对应到 dom 不能为空
// 会给这个 dom 注册点击事件,点击选择本地文件
browse_button: jQuery(".page-file-entities .action .upload"),
// 可以为空
// 默认值是 http://img.4ye.me/file_entities/uptoken
// 指定获取上传 token 的 url 地址
// 如果是开发模式需要指定自己的开发服务器地址
uptoken_url: 'http://img4ye-dev-ip:3000/file_entities/uptoken',
}
new Img4yeUploader(options)
});
</script>
</head>
<body>
<div class="page-file-entities">
<div class="action">
<div class="upload"></div>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/xx/jquery.min.js" />
<script src="http://img.4ye.me/assets/plugins/uploader.js" />
<script>
jQuery(function(){
var CustomFileProgress = (function() {
function CustomFileProgress($file_list_area, file) {
this.$file_list_area = $file_list_area;
this.file = file;
if (this.$file_list_area.find("#file_" + this.file.id).length === 0) {
this._add_dom();
}
this.$file = this.$file_list_area.find("#file_" + this.file.id);
}
CustomFileProgress.prototype.refresh_progress = function() {
return this.$file.find('.progress').text(this.file.percent + "%");
};
CustomFileProgress.prototype.upload_success = function(info) {
var res;
res = jQuery.parseJSON(info);
this.$file.find('.progress').text("上传成功");
if (res.kind === "image") {
this.$file.find('img').attr('src', res.url);
this.$file.find('img').show();
} else {
this.$file.find('img').hide();
}
this.$file.find('a.url').attr('href', res.url);
this.$file.find('a.url').text(res.url);
return this.$file.find('a.url').show();
};
CustomFileProgress.prototype.upload_end = function(status) {
console.log("upload_end");
return console.log("status " + status);
};
CustomFileProgress.prototype.upload_error = function() {
return this.$file.find('.progress').text("上传出错");
};
CustomFileProgress.prototype.start_upload = function() {
return this.$file.find('.progress').text("开始上传");
};
CustomFileProgress.prototype._add_dom = function() {
return jQuery("<div id='file_" + this.file.id + "' class='file'> <div class='name'>" + this.file.name + "</div> <div class='size'>文件大小:" + this.file.size + "K</div> <div class='progress'>正在准备上传</div> <img src='' style='display:none;'> <a class='url' style='display:none;' href=''></a> </div>").appendTo(this.$file_list_area);
};
return CustomFileProgress;
})();
var options = {
// 不能为空
// 指定一个 jquery selector str 或者 dom 或者 jQuery(dom),必须对应到 dom 不能为空
// 会给这个 dom 注册点击事件,点击选择本地文件
browse_button: jQuery(".page-file-entities .action .upload"),
// 可以为空
// 默认值是 http://img.4ye.me/file_entities/uptoken
// 指定获取上传 token 的 url 地址
// 如果是开发模式需要指定自己的开发服务器地址
uptoken_url: 'http://img4ye-dev-ip:3000/file_entities/uptoken',
// 可以为空
// 接受文件拖拽的 dom 区域
// 指定一个 jquery selector str 或者 dom 或者 jQuery(dom),可以为空
// 如果为空就表示不允许拖拽上传
drag_area: 'jQuery(".page-file-entities .drag")',
// 可以为空
// 默认值是 false
// 是否开启CTRL+V粘贴增加文件
paste_upload: true,
// 可以为空
// 指定一个 jquery selector str 或者 dom 或者 jQuery(dom),可以为空
// 用来显示文件上传列表的父DOM
file_list_area: jQuery(".page-file-entities .files"),
// 可以为空
// 当指定了 file_list_area 时,可以设置该回调类,用来显示上传列表
// 用法见下面的示例
file_progress_callback: CustomFileProgress
}
new Img4yeUploader(options)
});
</script>
</head>
<body>
<div class="page-file-entities">
<div class="action">
<div class="upload"></div>
</div>
<div class="drag">
可以把文件拖拽到该区域进行上传
</div>
<!-- 显示文件上传进度的列表-->
<div class="files">
</div>
</div>
</body>
</html>
var options = {
// 可以为空
// 默认值是 true
// 是否开启增加文件后,自动开始上传
// 建议开启
// 当是 false 的时候,增加文件到队列后,不会自动开始上传
// 而是需要主动调用 up.start() 方法开始上传
auto_start: false
....
}
var up = new Img4yeUploader(options)
// 通过点击 browse_button 选择增加文件到上传队列
// 或者通过拖拽文件到 drag_area 增加文件到上传队列
// 或者通过CTRL+V粘贴文件到上传队列
// 或者通过以下两个API增加文件到上传队列
up.add_file(file)
var base64_str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABLAAAAMiCAYAAAB+KDoJAAAgAElEQ…lYO/fto9GLgAiIgAiIgAiIgAiIgAiIgAiIgAiIwI+fwP8D7EH4YJpuLPYAAAAASUVORK5CYII="
up.add_file_by_base64(base64_str)
// 当 auto_start 参数是 false 的时候,通过以上任何形式,
// 只会增加文件到上传队列,不会开始上传
// 当 auto_start 参数是 true 的时候,通过以上任何形式增加文件到上传队列,
// 都会自动开始上传。
// 当 auto_start 参数是 false 的时候,
// 运行该方法后,就会对上传队列里的文件依次进行上传。
// 当 auto_start 参数是 true 的时候,不需要运行/不能运行 该方法,
// 运行该方法会报错。
// add_file add_file_by_base64 这个两个方法不要和 start 方法连用,
// 因为这两个方法不是堵塞的,而是异步的增加文件到上传队列
// 运行两个方法后大概需要200毫秒左右的时间才能把文件真正的增加到了上传队列
up.start()
随便记在这里而已,一般情况下不要直接回复。
这个服务有一个希望的卖点是针对开发者。比如方便他们在开发 web 或移动应用时使用图片。
这方面的需求值得研究。
自动图文排版服务是依赖这个服务的。
或许可以实现按颜色搜索图片?
不过算法方面可能需要考虑。大体上应该和地图搜索算法是类似的。
mongoDB 中的地理搜索原理:
http://docs.mongodb.org/manual/core/geospatial-indexes/
只要设计一种方法把图像颜色转为某种色谱中的 x, y 坐标并索引即可。
功能和体验部分:
运营和管理部分:
1 image.rb 创建回调进行转码(七牛转码是异步模型,需要一个队列发送转码请求,一个队列监控转码结果)
2 增加转码模型(用来记录转码状态和查询转码后文件的模型)
image.has_many :transcoding_records
transcoding_records
belongs_to :image
info # {:bit_rate => 128000}
qiniu_key # "/i/xxxx/xxxx.mp3"
status # processing success failure
quniu_persistance_id # 七牛的转码处理任务编号,可以用查询转码结果
音视频的源文件和图片源文件都是 image 保存(随后会改为 file_entity)
transcoding_records 会记录音视频转码后的文件
由于需要图片创建需要七牛请求才能实现。测试环境很难做到这一点。
所以需要制定一个方案用于图片测试(视频也可以参考)。
初始想法是这样:
需要实现一个规范的API,便于开发android客户端时,以及开发其他服务时调用。
URL: /api/upload
TYPE: POST
请求时应附带图片信息,图片信息放在请求参数的 file 字段中
HTTP 200 RESPONSE:
{
filename: 'xxxxxxxx.xxx',
url: 'http://img.teamkn.com/i/xxxxxxxx.xxx'
filesize: xxxxxx (单位字节)
width: xxx (单位像素)
height: xxx (单位像素)
major_color: #xxxxxx (颜色值)
}
引用 #5
第一轮 review 中发现的,需要修改的问题都画在这张图上了(截图来自目前的程序版本)
关于方形缩略图获取:其实任何一张图片,都可以使用目前图床的URL API来获取一个合适的方形版本。方法如下:
假设上传后的图片原始地址是:
http://img.teamkn.com/i/LySYblZU.jpg
先计算出 80dp 对应的像素值并取整,假设换算出来是160,则只要原始URL在后面加上 @160w_160h_1e_1c.png
,就可以取到合适的方形图片,很方便!
http://img.teamkn.com/i/LySYblZU.jpg@160w_160h_1e_1c.png
然后再把这个方形图片用于程序中的回显即可。建议使用 universal image loader
使用 Aliyun OSS Image Service
本次迁移用到了阿里云开放存储的图片处理服务, 需要在指定bucket上开通该功能, 并绑定域名至该bucket。图片处理的所有请求必须通过该绑定域名。
http://user_domain/path/to/object
后加上指定规格的参数即可, 图片处理流程交给阿里云图片服务;env.rb
和env.yml
里添加了配置项R::IMAGE_ENDPOINT
和IMAGE_ENDPOINT
, 指向绑定的域名;:old => true
,在程序逻辑里和迁移后产生的数据作区分;adaptive_width_500
)通过程序转换为可应用于阿里云图片处理服务的参数(如500w
).对应commit: 1660ecd
OSS图片处理服务文档:
针对图片服务使用场景,希望对典型的团队工作中用到图片的工作流程进行研究。
目前认为漫画汉化组的工作比较符合这种特征,因此针对汉化组的工作流程,和图片在工作流程中的用途,如何传播,如何使用,如何发布进行调研。调研过程记录和结果都提交到这个 issue 中。
** 2013 年 6 月 15 日更新 **
经过讨论,漫画汉化组由于以下原因而暂时不适合使用图片服务:
需要进一步寻找其他的团队场景。
http://kb.qiniu.com/571tr2gn
http://www.qiniu.com/pricing
使用自定义域名的要求是
1 必须是标准用户(手机+邮箱+身份认证 信息验证)
认证分为个人认证和企业认证(我注册的账号,提交个人认证只等待了两个小时就通过了)
2 账户余额大于10元可用
其实这是唯一的上传模式,无论是以下哪种上传流程
1 浏览器 -> img4ye 服务器 -> 七牛云存储
2 浏览器 -> 七牛云存储 -> 发送创建成功的信息给 img4ye 服务器
3 浏览器 -> 七牛云存储 -> 浏览器 -> 发送创建成功的信息给 img4ye 服务器
都需要 UploadToken
另外七牛官网文档中提到可以支持跨域上传
理论上跨域和UploadToken结合的话,可以支持浏览器直接上传文件到七牛云存储(支持整个文件上传和分段上传),而不经过 img4ye 服务器中转
跨域相关说明:
http://developer.qiniu.com/docs/v6/api/overview/security.html
这个API 七牛是有的
http://developer.qiniu.com/docs/v6/api/reference/fop/image/imageave.html
七牛自己写了 Ruby SDK,可以使用
http://developer.qiniu.com/docs/v6/sdk/ruby-sdk.html
七牛自己写了 JavaScript SDK,可以使用
http://developer.qiniu.com/docs/v6/sdk/javascript-sdk.html
1 上传读取云存储图片的核心逻辑
2 匿名上传
3 微博用户上传
4 匿名自定义尺寸设置
5 微博用户自定义尺寸设置
6 支持 短网址服务 生成缩略图上传的API
7 微博登陆
1 个人用户使用空间统计
2 图片增加 tag
3 用户邀请机制
4 QQ登陆
5 github登陆
暂时没有想到什么坑
1 新的逻辑需要可以读取旧的aliyun数据
2 新的逻辑需要可以读取写入新的qiniu数据
所以 images 需要加字段来支持以上逻辑
目前工程内用到的资源信息缺乏整理,需要整理到 wiki 里。
个人使用情况汇总逻辑(已上传图片数统计,已使用空间统计,尺寸配置数统计)
曾经实现过半成品插件:
https://github.com/kaid/chromium-ext-screenshot-demo
在此基础上重新实现针对 img4ye 0.3 的插件。
具体需求:
结合 img4ye 0.3 的逻辑,重构/重写插件并实现以下特性:
在 2015-4-1 修改中,图片上传(选择文件上传或粘贴上传)已经改为有进度条提示的形式。
目前已经部署到 img.4ye.me 可以体验。
但是目前还存在以下的已知遗留问题:
还有任何问题请反馈给宋亮。
访问项目 /zmkm 可以上传非用户私有图片
访问项目 / 可以用 github weibo qq 登陆
登陆成功并输入邀请码后,访问 / 可以上传用户私有图片
工程根目录,运行 rake invitations:create count=5 可以创建五个邀请码
访问项目 / 可以用 github weibo qq 登陆
登陆成功后输入邀请码后才能正常访问 / 上传用户私有图片
登陆后首页就可以上传用户私有图片
使用 ajax 请求设置 tag
url: "/images/:token/add_tags"
method: post
params:
tags "tag1,tag2"
# 个人使用空间字节数
user.used_space_size
# 个人使用空间(友好的阅读格式)
user.used_space_size_str
访问项目 /zmkm/settings 可以设置非用户私有图片的自定义尺寸
访问项目 /settings 可以设置用户自己私有图片的自定义尺寸
李飞推荐的网站:
https://www.shiyanlou.com/
双方可以对着一个虚拟桌面实时协作。感觉上可以用于团队协作或者编程教学场景。优点是,比 teamviewer 对带宽依赖更小。
https://bearyboard.com
设计稿沟通网站。最大的优点是可以实时标注,并让对方看到。
实现实时协作可以用到 websocket,以前肖少富做过调研。
目前来看开发方面最简便的框架是 faye,性能另说。
http://stackoverflow.com/questions/4893720/faye-vs-socket-io-and-juggernaut
http://123.paomianba.com/
泡面吧目前从功能网站变成了媒体网站。上面是他的一个导航网址。
设计稿沟通服务是否需要 freeze 的特性,这一点需要去和设计师们沟通。
需要的获取数据API设计如下
列出每天的用户注册数量和详细名单,可以以月为单位选择时间范围。
url
/users/sign_stat_data
method
get
params
# 获取 2015 年 5 月的每日注册人数和名单
time 2015-05
response
{
:time => "2015-05",
:data => {
"01" => {
#01 号 注册 10 人
:count => 10,
# 详细名单
:users => [
{:id => xxx, :name => xxx, :email => xxx},
.........................................
]
},
"02" => {
#02 号 注册 20 人
:count => 20,
# 详细名单
:users => [
{:id => xxx, :name => xxx, :email => xxx},
.........................................
]
},
......
"31" => {
#31 号 注册 50 人
:count => 50,
# 详细名单
:users => [
{:id => xxx, :name => xxx, :email => xxx},
.........................................
]
},
}
}
需要的获取数据API设计如下
列出每天的上传的图片数量,可以以月为单位选择时间范围。
url
/images/upload_count_stat_data
method
get
params
# 获取 2015 年 5 月的每日上传图片数量
time 2015-05
response
{
:time => "2015-05",
:data => {
"01" => {
#01 号 上传 30 张
:count => 30
},
"02" => {
#02 号 上传 69 张
:count => 69
},
......
"31" => {
#31 号 上传 134 张
:count => 134
}
}
}
目前 img4ye 中图片文件的路径是形如:
http://img.teamkn.com/image_service/images/kpmlDTBA/kpmlDTBA.png
这样的路径,由于一些历史原因(原来是本地存储图片,后来改成了云存储),这个URL较冗余。
为了优化体验,需要调整为更短的URL。
这个调整分为两方面工作:
所有路径类似:
http://img.teamkn.com/image_service/images/kpmlDTBA/kpmlDTBA.png
的旧文件,都在OSS上复制一份到新路径:
http://img.teamkn.com/i/kpmlDTBA.png
文件名不变,路径简化为 /i/
将来上传的新文件都使用如下的URL:
http://img.teamkn.com/i/#{randstr(8)}.#{extname}
之前的某次数据迁移也引入了一个数据库记录标记,这次也应该去掉。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.