美文网首页
图床——基于七牛JS-SDK和KVDB

图床——基于七牛JS-SDK和KVDB

作者: SkyWatcher | 来源:发表于2015-06-10 11:12 被阅读762次

    原文链接:图床——基于七牛JS-SDK和KVDB

    浏览浏览

    上传

    服务端获取token

    # -*- coding: utf-8 -*-
    __author__ = 'Sky'
    
    import qiniu
    from datetime import datetime
    import config
    
    
    def get_token():
        q = qiniu.Auth(config.QINIU_ACCESS_KEY, config.QINIU_SECRET_KEY)
        # print str(datetime.now())
        token = q.upload_token(config.PIC_BUCKET)
        return token
    

    JS上传到七牛

    详细使用可参考七牛JS-SDK

    var uploader = Qiniu.uploader({
        runtimes: 'html5,flash,html4',
        browse_button: 'pickfiles',
        container: 'container',
        drop_element: 'container',
        max_file_size: '100mb',
        filters: {
            mime_types: [
                { title: "图片文件", extensions: "jpg,gif,png,bmp" }
            ],
            prevent_duplicates: true //不允许队列中存在重复文件
        },
        flash_swf_url: '/static/js/plupload/Moxie.swf',
        dragdrop: true,
        chunk_size: '4mb',
        uptoken_url: $('#uptoken_url').val(),
        domain: $('#domain').val(),
        auto_start: true,
        init: {
            'FilesAdded': function(up, files) {
                $('table').show();
                $('#success').hide();
                plupload.each(files, function(file) {
                    var progress = new FileProgress(file, 'fsUploadProgress');
                    progress.setStatus("等待...");
                });
            },
            'BeforeUpload': function(up, file) {
                var progress = new FileProgress(file, 'fsUploadProgress');
                var chunk_size = plupload.parseSize(this.getOption('chunk_size'));
                if (up.runtime === 'html5' && chunk_size) {
                    progress.setChunkProgess(chunk_size);
                }
            },
            'UploadProgress': function(up, file) {
                var progress = new FileProgress(file, 'fsUploadProgress');
                var chunk_size = plupload.parseSize(this.getOption('chunk_size'));
                progress.setProgress(file.percent + "%", up.total.bytesPerSec, chunk_size);
    
            },
            'UploadComplete': function() {
                $('#success').show();
            },
            'FileUploaded': function(up, file, info) {
                var progress = new FileProgress(file, 'fsUploadProgress');
                progress.setComplete(up, info);
                var res = $.parseJSON(info);
                // 请求后台存储
                var domain = up.getOption('domain');
                //url = domain + encodeURI(res.key);
                var link = domain + res.key;
                var key = res.key;
                $.ajax({
                    url:"/upQiniu",
                    type: "POST",
                    data: { key: key, url: link}
                })
                .done(function(data){
                    if(data === 'error') {
                        alert('上传失败');
                        location.reload(true);
                    }
                });
            },
            'Error': function(up, err, errTip) {
                $('table').show();
                var progress = new FileProgress(err.file, 'fsUploadProgress');
                progress.setError();
                progress.setStatus(errTip);
            }
            ,
            'Key': function(up, file) {
                //当前时间戳
                var key = new Date();
                return key.getTime()
            }
        }
    });
    

    保存信息到KVDB

    # -*- coding: utf-8 -*-
    __author__ = 'Sky'
    
    import sae
    import json
    import sae.kvdb
    
    class KvdbStorage():
        # 初始化kvdb
        def __init__(self):
            self.kv = sae.kvdb.KVClient()
    
        # 获取value
        def get_value(self, key):
            return self.kv.get(key)
    
        # 获取dict_value
        def get(self, key):
            string_value = self.kv.get(key)
            if string_value is None:
                return None
            return decode_dict(string_value)
    
        # 设置value
        def set_value(self, key, value):
            self.kv.set(key, value)
    
        # 设置dict_value
        def set(self, key, dict_value):
            string_value = encode_dict(dict_value)
            self.kv.set(key, string_value)
    
        # 批量获取key
        def getkeys_by_prefix(self, prefix, limit=100, marker=None):
            return list(self.kv.getkeys_by_prefix(prefix, limit=limit, marker=marker))
    
        # 批量获取key/value
        def get_by_prefix(self, prefix, limit=100, marker=None):
            return self.kv.get_by_prefix(prefix, limit=limit, marker=marker)
    
        # 删除key
        def delete(self, key):
            self.kv.delete(key)
    
    # 编码字典
    def encode_dict(my_dict):
        return "\x1e".join("%s\x1f%s" % x for x in my_dict.iteritems())
    
    # 解码字典
    def decode_dict(my_string):
        return dict(x.split("\x1f") for x in my_string.split("\x1e"))
    
    • 只存储了key和图片url,其他暂时是固定信息,便于以后扩展。
    # 上传文件到七牛
    @app.route('/upQiniu', methods=['POST', 'GET'])
    def upQiniu():
        if request.form.get('key'):
            url = request.form.get('url')
            upkey = request.form.get('key')
            # 时间差,用于加载排序
            import time
            future_time = int(time.mktime(datetime.strptime('3000-01-01 00:00:00.000', "%Y-%m-%d %H:%M:%S.%f").timetuple()) * 1000)
            uid = future_time - int(upkey)
            # 存入DB
            key = 'picbed_%s' % uid
            object = 'Sunset Lake'
            words = 'A peaceful sunset view...'
            author = 'skyway'
            # print key
            data = {'upkey': upkey, 'object': object, 'words': words, 'author': author, 'url': url}
            kv.set(str(key), data)
            # kv.set_value(str(key), url)
            return 'success'
    

    浏览

    访问获取key

    # 初始加载
    key_values = kv.get_by_prefix('picbed_', 20, None)
    # print sorted(kv.getkeys_by_prefix('picbed', 3, None))
    data = tuple(key_values)
    json_data = []
    for item in data:
        tmp = {}
        tmp['key'] = item[0]
        if '\x1e' in item[1]:
            content = decode_dict(item[1])
            # print content
            tmp['url'] = content['url'] + "?imageView2/2/w/400/format/jpg"
            tmp['object'] = content['object']
            tmp['words'] = content['words']
            tmp['upkey'] = content['upkey']
            tmp['author'] = content['author']
        else:
            tmp['url'] = item[1] + "?imageView2/2/w/400/format/jpg"
            tmp['object'] = 'Sunset Lake'
            tmp['words'] = 'A peaceful sunset view...'
            tmp['upkey'] = item[1][-13:]
            tmp['author'] = 'skyway'
        json_data.append(tmp)
    # data = sorted(data, reverse=True)
    # print data
    return render_template('PicBed.html', data=json_data, domain=config.PIC_DOMAIN)
    

    瀑布流和数据加载

    • Server端返回json数据
    # 加载更多
    if request.form.get('key'):
        key = request.form.get('key')
        # print key
        key_values = kv.get_by_prefix('picbed_', 10, key)
        # print sorted(kv.getkeys_by_prefix('picbed', 3, key))
        data = tuple(key_values)
        # data = sorted(data, reverse=True)
        print data
        json_data = []
        for item in data:
            tmp = {}
            tmp['key'] = item[0]
            if '\x1e' in item[1]:
                content = decode_dict(item[1])
                # print content
                tmp['url'] = content['url'] + "?imageView2/2/w/400/format/jpg"
                tmp['object'] = content['object']
                tmp['words'] = content['words']
                tmp['upkey'] = content['upkey']
                tmp['author'] = content['author']
            else:
                tmp['url'] = item[1] + "?imageView2/2/w/400/format/jpg"
                tmp['object'] = 'Sunset Lake'
                tmp['words'] = 'A peaceful sunset view...'
                tmp['upkey'] = item[1][-13:]
                tmp['author'] = 'skyway'
            json_data.append(tmp)
        json_str = json.dumps(json_data)
        return json_str
    
    • 加载更多和渲染数据:
    $(window).scroll(function () {
        var clientHeight = $(window).height(),
            scrollTop = $(window).scrollTop(),
            scrollHeight = $(document).height();
        if (!isScroll && (scrollHeight - clientHeight - scrollTop < 500)) {
            isScroll = 1;
            $('#loading').show();
            // 获取最后一个块的key
            var key = $('.grid:last-child').data('key');
            // 请求数据
            $.ajax({
                url:"/picbed",
                type: "POST",
                data: { key: key}
            })
            .done(function(data){
                if(data === 'error') {
                    alert('加载失败');
                    location.reload(true);
                    return false;
                }
                var pics = JSON.parse(data);
                //没有更多了
                if(jQuery.isEmptyObject(pics)){
                    $('#load_img').hide();
                    $('#load_text').text('没有更多了!');
                    $('#contain').BlocksIt('reload');
                    return false;
                }
    
                $.each(pics, function(index, val){
                    var add =
                            "<div class='grid' data-key='" + this.key +"'>" +
                                "<div class='imgholder'>" +
                                    "<a class='fopLink' data-key='"+ this.upkey + "'>" +
                                        "<img class='img_load' src='" + this.url +"' />" +
                                    "</a>" +
                                "</div>" +
                                "<span class='stop'></span>" +
                                "<strong>"+ this.object +"</strong>" +
                                "<div class='description'>" +
                                    "<p>"+ this.words +"</p>" +
                                    "<div class='meta'>by " + this.author +"</div>" +
                                "</div>"+
                            "</div>";
                    $("#contain").append(add);
                    // 动态加载渲染图片
                    img_stop();
                });
                $('#contain').BlocksIt('reload');
            });
        }
    });
    
    • 瀑布流效果使用插件Blockits.js
      效果不是很好,会产生重叠

    长图渲染

    对于过长的图片,影响整个浏览的体验,于是超过一定长度的图片,超出部分隐藏,并在图片尾部添加波浪表示图片未展示完全。

    // 渲染图片函数
    var img_stop = function(){
        var height = 800;
        $('.img_load').each(function() {
            $(this).load(function(){
                if( $(this).height() > height){
                    $(this).parent().parent().next().css('display', 'block');
                }
            });
        });
    };
    
    // 初始加载渲染图片
    $(function(){
        img_stop();
    });
    
    var img_load = function(url, key) {
        var img = new Image();
        img.src = url;
        img.onload = load_img(img, key);
        function load_img(img, key){
            var height = img.height;
            if( height > 500){
                var str = 'div[data-key=' + key + ']';
                $(str).find('.stop').css('display', 'block');
            }
        }
    };
    

    效果

    • PC端


      浏览浏览
      上传上传
      预览预览
    • 移动端


      浏览浏览 上传上传 预览预览

    GitHub源码

    相关文章

      网友评论

          本文标题:图床——基于七牛JS-SDK和KVDB

          本文链接:https://www.haomeiwen.com/subject/bprjqttx.html