Пример #1
0
def userupload():
    # 通过base64形式上传图片
    res = dict(code=1, msg=None)
    picStr = request.form.get('picStr')
    if picStr:
        # 判断是否上传到又拍云还是保存到本地
        if Upyun['enable'] in ('true', 'True', True):
            basedir = Upyun['basedir'] if Upyun['basedir'].startswith('/') else "/" + Upyun['basedir']
            imgUrl = os.path.join(basedir, gen_rnd_filename() + ".png")
            try:
                # 又拍云存储封装接口
                UploadImage2Upyun(imgUrl, base64.b64decode(picStr))
            except Exception, e:
                logger.error(e, exc_info=True)
                res.update(code=2, msg="System is abnormal")
            else:
                imgUrl = Upyun['dn'].strip("/") + imgUrl
                res.update(imgUrl=imgUrl, code=0)
        else:
            filename = gen_rnd_filename() + ".png"
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            with open(os.path.join(UPLOAD_FOLDER, filename), "wb") as f:
                f.write(base64.b64decode(picStr))
            imgUrl = request.url_root + IMAGE_FOLDER + filename
            res.update(imgUrl=imgUrl, code=0)
        # "回调"动作
        if res.get("imgUrl"):
            imgUrl = res.get("imgUrl")
            callableAction = request.args.get("callableAction")
            if callableAction == "UpdateAvatar":
                resp = g.api.userprofile.updateUserAvatar(uid=g.uid, avatarUrl=imgUrl)
                res.update(resp)
                if resp["code"] == 0:
                    # 同步头像
                    g.api.usersso.clientsConSync(g.api.userapp.getUserApp, g.uid, dict(CallbackType="user_avatar", CallbackData=imgUrl))
Пример #2
0
def userupload():
    # 通过base64形式上传图片
    res = dict(code=1, msg=None)
    picStr = request.form.get('picStr')
    if picStr:
        # 判断是否上传到picbed图床、又拍云还是保存到本地
        if PICBED['enable'] in ('true', 'True', True):
            try:
                resp = requests.post(
                    PICBED["api"],
                    data=dict(picbed=picStr, album="passport"),
                    headers=dict(Authorization="LinkToken %s" %
                                 PICBED["LinkToken"]),
                    timeout=5).json()
                if not isinstance(resp, dict):
                    raise
            except Exception as e:
                res.update(code=4, msg=e)
            else:
                if resp.get('code') == 0:
                    res.update(imgUrl=resp['src'], code=0)
                else:
                    res.update(resp)
        elif Upyun['enable'] in ('true', 'True', True):
            basedir = Upyun['basedir'] if Upyun['basedir'].startswith(
                '/') else "/" + Upyun['basedir']
            imgUrl = os.path.join(basedir, gen_rnd_filename() + ".png")
            try:
                # 又拍云存储封装接口
                UploadImage2Upyun(imgUrl, base64.b64decode(picStr))
            except Exception, e:
                logger.error(e, exc_info=True)
                res.update(code=2, msg="System is abnormal")
            else:
                imgUrl = Upyun['dn'].strip("/") + imgUrl
                res.update(imgUrl=imgUrl, code=0)
        else:
            filename = gen_rnd_filename() + ".png"
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            with open(os.path.join(UPLOAD_FOLDER, filename), "wb") as f:
                f.write(base64.b64decode(picStr))
            imgUrl = request.url_root + IMAGE_FOLDER + filename
            res.update(imgUrl=imgUrl, code=0)
        # "回调"动作
        if res.get("imgUrl"):
            imgUrl = res.get("imgUrl")
            callableAction = request.args.get("callableAction")
            if callableAction == "UpdateAvatar":
                resp = g.api.userprofile.updateUserAvatar(uid=g.uid,
                                                          avatarUrl=imgUrl)
                res.update(resp)
                if resp["code"] == 0:
                    # 同步头像
                    g.api.usersso.clientsConSync(
                        g.api.userapp.getUserApp, g.uid,
                        dict(CallbackType="user_avatar", CallbackData=imgUrl))
Пример #3
0
def userupload():
    # 通过base64形式上传图片
    res = dict(code=1, msg=None)
    picStr = request.form.get('picStr')
    callableAction = request.args.get("callableAction")
    if picStr:
        basedir = Upyun['basedir'] if Upyun['basedir'].startswith(
            '/') else "/" + Upyun['basedir']
        imgUrl = os.path.join(basedir, gen_rnd_filename() + ".png")
        try:
            # 又拍云存储封装接口
            upyunapi = CloudStorage(timeout=15)
            upyunapi.put(imgUrl, base64.b64decode(picStr))
        except Exception, e:
            logger.error(e, exc_info=True)
            res.update(code=2, msg="System is abnormal")
        else:
            imgUrl = Upyun['dn'].strip("/") + imgUrl
            res.update(imgUrl=imgUrl, code=0)
            if callableAction == "UpdateAvatar":
                resp = g.api.userprofile.updateUserAvatar(uid=g.uid,
                                                          avatarUrl=imgUrl)
                res.update(resp)
                if resp["code"] == 0:
                    # 同步头像
                    g.api.usersso.clientsConSync(
                        g.api.userapp.getUserApp, g.uid,
                        dict(CallbackType="user_avatar", CallbackData=imgUrl))
Пример #4
0
def upload_view():
    res = dict(code=-1, msg=None)
    logger.debug(request.files)
    f = request.files.get('file')
    if f and allowed_file(f.filename):
        filename = secure_filename(gen_rnd_filename() + "." +
                                   f.filename.split('.')[-1])  #随机命名
        basedir = Upyun['basedir'] if Upyun['basedir'].startswith(
            '/') else "/" + Upyun['basedir']
        imgUrl = os.path.join(basedir, filename)
        try:
            upres = api.put(imgUrl, f.stream.read())
        except Exception, e:
            logger.error(e, exc_info=True)
            res.update(code=2, msg="Storage failure")
        else:
            imgId = md5(filename)
            imgUrl = Upyun['dn'].strip("/") + imgUrl
            upres.update(ctime=get_current_timestamp(),
                         imgUrl=imgUrl,
                         imgId=imgId)
            try:
                pipe = g.redis.pipeline()
                pipe.sadd(picKey, imgId)
                pipe.hmset("{}:{}".format(GLOBAL['ProcessName'], imgId), upres)
                pipe.execute()
            except Exception, e:
                logger.error(e, exc_info=True)
                res.update(
                    code=0,
                    msg=
                    "It has been uploaded, but the server has encountered an unknown error"
                )
            else:
Пример #5
0
def UploadAvatarImage():
    logger.sys.debug(request.files)
    f = request.files.get('file')
    # Check if the file is one of the allowed types/extensions
    if f and allowed_file(f.filename):
        filename = secure_filename(gen_rnd_filename() + "." +
                                   f.filename.split('.')[-1])  #随机命名
        if PLUGINS['UpYunStorage']['enable'] in ('true', 'True', True):
            imgUrl = "/EauDouce/avatar/" + filename
            upres = UploadImage2Upyun(imgUrl, f.stream.read())
            imgUrl = PLUGINS['UpYunStorage']['dn'].strip("/") + imgUrl
            logger.sys.info(
                "Avatar to Upyun file saved, its url is %s, result is %s" %
                (imgUrl, upres))
        else:
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            f.save(os.path.join(UPLOAD_FOLDER, filename))
            imgUrl = "/" + IMAGE_FOLDER + filename
            logger.sys.info("Avatar to local file saved in %s, its url is %s" %
                            (UPLOAD_FOLDER, imgUrl))
        # return user home and write avatar url into mysql db.
        res = g.api.user_update_avatar(g.username, imgUrl)
    else:
        res = {"success": False, "msg": u"上传失败: 未成功获取文件或格式不允许"}

    logger.sys.info(res)
    return jsonify(res)
Пример #6
0
def test():
    logger.sys.debug(request.files)
    f = request.files.get('file')
    # Check if the file is one of the allowed types/extensions
    if f and allowed_file(f.filename):
        filename = secure_filename(gen_rnd_filename() + "." +
                                   f.filename.split('.')[-1])  #随机命名
        if PLUGINS['UpYunStorage']['enable'] in ('true', 'True', True):
            imgUrl = "/EauDouce/test/" + filename
            upres = UploadImage2Upyun(imgUrl, f.stream.read())
            imgUrl = PLUGINS['UpYunStorage']['dn'].strip("/") + imgUrl
            logger.sys.info(
                "TEST to Upyun file saved, its url is %s, result is %s" %
                (imgUrl, upres))
        else:
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            f.save(os.path.join(UPLOAD_FOLDER, filename))
            imgUrl = "/" + IMAGE_FOLDER + filename
            logger.sys.info("TEST to local file saved in %s, its url is %s" %
                            (UPLOAD_FOLDER, imgUrl))
        res = dict(code=0, imgUrl=imgUrl)
    else:
        res = {"code": -1, "msg": u"上传失败: 未成功获取文件或格式不允许"}

    logger.sys.info(res)
    return jsonify(res)
Пример #7
0
def UploadClipperAvatar():
    if request.form.get("action") == "add":
        data = request.form.get("picStr")
        imgdata = base64.b64decode(data)
        filename = gen_rnd_filename() + ".png"  #随机命名
        if PLUGINS['UpYunStorage']['enable'] in ('true', 'True', True):
            imgUrl = "/EauDouce/avatar/" + filename
            upres = UploadImage2Upyun(imgUrl, base64str(data))
            imgUrl = PLUGINS['UpYunStorage']['dn'].strip("/") + imgUrl
            logger.sys.info(
                "Avatar to Upyun file saved, its url is %s, result is %s" %
                (imgUrl, upres))
        else:
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            file = open(os.path.join(UPLOAD_FOLDER, filename), 'wb')
            file.write(imgdata)
            file.close()
            imgUrl = "/" + IMAGE_FOLDER + filename
            logger.sys.info("Avatar to local file saved in %s, its url is %s" %
                            (UPLOAD_FOLDER, imgUrl))
        # return user home and write avatar url into mysql db.
        res = g.api.user_update_avatar(g.username, imgUrl)
    else:
        res = {"success": False, "msg": u"不支持的action"}

    logger.sys.info(res)
    return jsonify(res)
Пример #8
0
def useruploadpub():
    # 通过表单形式上传图片
    res = dict(code=1, msg=None)
    logger.debug(request.files)
    f = request.files.get('file')
    callableAction = request.args.get("callableAction")
    if f and allowed_file(f.filename):
        filename = gen_rnd_filename() + "." + secure_filename(
            f.filename).split('.')[-1]  # 随机命名
        # 判断是否上传到又拍云还是保存到本地
        if Upyun['enable'] in ('true', 'True', True):
            basedir = Upyun['basedir'] if Upyun['basedir'].startswith(
                '/') else "/" + Upyun['basedir']
            imgUrl = os.path.join(basedir, filename)
            try:
                # 又拍云存储封装接口
                UploadImage2Upyun(imgUrl, f.stream.read())
            except Exception, e:
                logger.error(e, exc_info=True)
                res.update(code=2, msg="System is abnormal")
            else:
                imgUrl = Upyun['dn'].strip("/") + imgUrl
                res.update(data=dict(src=imgUrl), code=0)
        else:
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            f.save(os.path.join(UPLOAD_FOLDER, filename))
            imgUrl = request.url_root + IMAGE_FOLDER + filename
            res.update(data=dict(src=imgUrl), code=0)
Пример #9
0
def useruploadpub():
    # 通过表单形式上传图片
    res = dict(code=1, msg=None)
    logger.debug(request.files)
    f = request.files.get('file')
    callableAction = request.args.get("callableAction")
    if f and allowed_file(f.filename):
        filename = gen_rnd_filename() + "." + secure_filename(
            f.filename).split('.')[-1]  # 随机命名
        # 判断是否上传到又拍云还是保存到本地
        if PICBED['enable'] in ('true', 'True', True):
            try:
                files = {
                    'picbed': (filename, f.stream.read(),
                               'image/%s' % filename.split(".")[-1])
                }
                resp = requests.post(
                    PICBED["api"],
                    files=files,
                    data=dict(album="passport"),
                    headers=dict(Authorization="LinkToken %s" %
                                 PICBED["LinkToken"]),
                    timeout=5).json()
                if not isinstance(resp, dict):
                    raise
            except Exception as e:
                res.update(code=4, msg=e)
            else:
                if resp.get('code') == 0:
                    res.update(data=dict(src=resp['src']), code=0)
                else:
                    res.update(resp)
        elif Upyun['enable'] in ('true', 'True', True):
            basedir = Upyun['basedir'] if Upyun['basedir'].startswith(
                '/') else "/" + Upyun['basedir']
            imgUrl = os.path.join(basedir, filename)
            try:
                # 又拍云存储封装接口
                UploadImage2Upyun(imgUrl, f.stream.read())
            except Exception, e:
                logger.error(e, exc_info=True)
                res.update(code=2, msg="System is abnormal")
            else:
                imgUrl = Upyun['dn'].strip("/") + imgUrl
                res.update(data=dict(src=imgUrl), code=0)
        else:
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            f.save(os.path.join(UPLOAD_FOLDER, filename))
            imgUrl = request.url_root + IMAGE_FOLDER + filename
            res.update(data=dict(src=imgUrl), code=0)
Пример #10
0
def upload_view():
    res = dict(code=-1, msg=None)
    label = request.args.get("label")
    _has_label = lambda label: g.redis.sismember(
        current_app.config["labelKey"], label
    ) and g.redis.exists("{}:label:{}".format(GLOBAL['ProcessName'], label)
                         ) or label == current_app.config["labelDefault"]
    if not label:
        label = current_app.config["labelDefault"]
    if label and _has_label(label):
        f = request.files.get('file')
        if f and allowed_file(f.filename):
            filename = secure_filename(gen_rnd_filename() + "." +
                                       f.filename.split('.')[-1])  #随机命名
            basedir = Upyun['basedir'] if Upyun['basedir'].startswith(
                '/') else "/" + Upyun['basedir']
            imgUrl = os.path.join(basedir, filename)
            try:
                upres = api.put(imgUrl, f.stream.read())
            except Exception, e:
                logger.error(e, exc_info=True)
                res.update(code=2, msg="Storage failure")
            else:
                imgId = md5(filename)
                imgUrl = Upyun['dn'].strip("/") + imgUrl
                upres.update(ctime=get_current_timestamp(),
                             imgUrl=imgUrl,
                             imgId=imgId,
                             label=label)
                try:
                    pipe = g.redis.pipeline()
                    pipe.sadd(current_app.config["picKey"], imgId)
                    pipe.hmset("{}:{}".format(GLOBAL['ProcessName'], imgId),
                               upres)
                    pipe.hincrby(
                        "{}:label:{}".format(GLOBAL['ProcessName'], label),
                        "imgNum")
                    pipe.execute()
                except Exception, e:
                    logger.error(e, exc_info=True)
                    res.update(
                        code=0,
                        msg=
                        "It has been uploaded, but the server has encountered an unknown error"
                    )
                else:
                    logger.info(
                        "Upload to Upyun file saved, its url is %s, result is %s, imgId is %s"
                        % (imgUrl, upres, imgId))
                    res.update(code=0, imgUrl=imgUrl)
Пример #11
0
def useruploadpub():
    # 通过表单形式上传图片
    res = dict(code=1, msg=None)
    logger.debug(request.files)
    f = request.files.get('file')
    callableAction = request.args.get("callableAction")
    if f and allowed_file(f.filename):
        filename = secure_filename(gen_rnd_filename() + "." + f.filename.split('.')[-1])  # 随机命名
        basedir = Upyun['basedir'] if Upyun['basedir'].startswith('/') else "/" + Upyun['basedir']
        imgUrl = os.path.join(basedir, filename)
        try:
            # 又拍云存储封装接口
            upyunapi = CloudStorage(timeout=15)
            upyunapi.put(imgUrl, f.stream.read())
        except Exception, e:
            logger.error(e, exc_info=True)
            res.update(code=2, msg="System is abnormal")
        else:
            imgUrl = Upyun['dn'].strip("/") + imgUrl
            res.update(data=dict(src=imgUrl), code=0)
Пример #12
0
def UploadBlogImage():
    editorType = request.args.get("editorType", "wangEditor")
    logger.sys.debug(request.files)
    f = request.files.get("WriteBlogImage") or request.files.get(
        "editormd-image-file")
    if f and allowed_file(f.filename):
        filename = secure_filename(gen_rnd_filename() + "." +
                                   f.filename.split('.')[-1])  #随机命名
        if PLUGINS['UpYunStorage']['enable'] in ('true', 'True', True):
            imgUrl = "/EauDouce/blog/" + filename
            upres = UploadImage2Upyun(imgUrl, f.stream.read())
            imgUrl = PLUGINS['UpYunStorage']['dn'].strip("/") + imgUrl
            logger.sys.info(
                "Blog to Upyun file saved, its url is %s, result is %s" %
                (imgUrl, upres))
        else:
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            f.save(os.path.join(UPLOAD_FOLDER, filename))
            imgUrl = request.url_root + IMAGE_FOLDER + filename
            logger.sys.info("Blog to local file saved in %s, its url is %s" %
                            (UPLOAD_FOLDER, imgUrl))
        #返回数据加上自定义头
        if editorType == "wangEditor":
            res = Response(imgUrl)
            res.headers["ContentType"] = "text/html"
        else:
            res = jsonify(url=imgUrl, message=None, success=1)
            res.headers["ContentType"] = "application/json"
    else:
        result = r"error|未成功获取文件或格式不允许,上传失败"
        if editorType == "wangEditor":
            res = Response(result)
            res.headers["ContentType"] = "text/html"
        else:
            res = jsonify(message=result, success=0)
            res.headers["ContentType"] = "application/json"
    res.headers["Charset"] = "utf-8"
    return res
Пример #13
0
def upload():
    """上传逻辑:
    0. 判断是否登录,如果未登录则判断是否允许匿名上传
    1. 获取上传的文件,判断允许格式
    2. 生成文件名、唯一sha值、上传目录等,选择图片存储的后端钩子(单一)
        - 存储图片的钩子目前版本仅一个,默认是up2local(如果禁用则保存失败)
    3. 解析钩子数据,钩子回调数据格式:{code=?, sender=hook_name, src=?}
        - 后端保存失败或无后端的情况都要立刻返回响应
    4. 此时保存图片成功,持久化存储到全局索引、用户索引
    5. 返回响应:{code:0, data={src=?, sender=success_saved_hook_name}}
    """
    res = dict(code=1, msg=None)
    #: 匿名上传开关检测
    if not is_true(g.cfg.anonymous) and not g.signin:
        res.update(code=403, msg="Anonymous user is not sign in")
        return res
    f = request.files.get('picbed')
    #: 实时获取后台配置中允许上传的后缀,如: jpg|jpeg|png
    allowed_suffix = partial(allowed_file,
                             suffix=parse_valid_verticaline(g.cfg.upload_exts))
    if f and allowed_suffix(f.filename):
        try:
            g.rc.ping()
        except RedisError as e:
            logger.error(e, exc_info=True)
            res.update(code=2, msg="Program data storage service error")
            return res
        stream = f.stream.read()
        suffix = splitext(f.filename)[-1]
        filename = secure_filename(f.filename)
        if "." not in filename:
            filename = "%s%s" % (generate_random(8), suffix)
        #: 根据文件名规则重定义图片名
        upload_file_rule = g.cfg.upload_file_rule
        if upload_file_rule in ("time1", "time2", "time3"):
            filename = "%s%s" % (gen_rnd_filename(upload_file_rule), suffix)
        #: 上传文件位置前缀规则
        upload_path_rule = g.cfg.upload_path_rule
        if upload_path_rule == 'date1':
            upload_path = get_today("%Y/%m/%d")
        elif upload_path_rule == 'date2':
            upload_path = get_today("%Y%m%d")
        else:
            upload_path = ''
        upload_path = join(g.userinfo.username or 'anonymous', upload_path)
        #: 定义文件名唯一索引
        sha = "sha1.%s.%s" % (get_current_timestamp(True), sha1(filename))
        #: 定义保存图片时仅使用某些钩子,如: up2local
        #: TODO 目前版本仅允许设置了一个,后续考虑聚合
        includes = parse_valid_comma(g.cfg.upload_includes or 'up2local')
        if len(includes) > 1:
            includes = [choice(includes)]
        #: TODO 定义保存图片时排除某些钩子,如: up2local, up2other
        # excludes = parse_valid_comma(g.cfg.upload_excludes or '')
        #: 钩子返回结果(目前版本最终结果中应该最多只有1条数据)
        data = []

        #: 保存图片的钩子回调
        def callback(result):
            logger.info(result)
            if result["sender"] == "up2local":
                result["src"] = url_for("static",
                                        filename=join(UPLOAD_FOLDER,
                                                      upload_path, filename),
                                        _external=True)
            data.append(dfr(result))

        #: 调用钩子中upimg_save方法
        current_app.extensions["hookmanager"].call(
            _funcname="upimg_save",
            _callback=callback,
            _include=includes,
            filename=filename,
            stream=stream,
            upload_path=upload_path,
            local_basedir=join(current_app.root_path,
                               current_app.static_folder, UPLOAD_FOLDER))
        #: 判定后端存储全部失败时,上传失败
        if not data:
            res.update(code=1, msg="No valid backend storage service")
            return res
        if len(data) == len([i for i in data if i.get("code") != 0]):
            res.update(
                code=1,
                msg="All backend storage services failed to save pictures")
            return res
        #: 存储数据
        defaultSrc = data[0]["src"]
        pipe = g.rc.pipeline()
        pipe.sadd(rsp("index", "global"), sha)
        if g.signin and g.userinfo.username:
            pipe.sadd(rsp("index", "user", g.userinfo.username), sha)
        pipe.hmset(
            rsp("image", sha),
            dict(
                sha=sha,
                filename=filename,
                upload_path=upload_path,
                user=g.userinfo.username if g.signin else 'anonymous',
                ctime=get_current_timestamp(),
                status='enabled',  # disabled, deleted
                src=defaultSrc,
                sender=data[0]["sender"],
                senders=json.dumps(data)))
        try:
            pipe.execute()
        except RedisError as e:
            logger.error(e, exc_info=True)
            res.update(code=3, msg="Program data storage service error")
        else:
            res.update(
                code=0,
                filename=filename,
                sender=data[0]["sender"],
                api=url_for("api.shamgr", sha=sha, _external=True),
            )
            #: format指定图片地址的显示字段,默认src,可以用点号指定
            #: 比如data.src,那么返回格式{code, filename..., data:{src}, ...}
            fmt = request.form.get("format", request.args.get("format"))
            res.update(format_upload_src(fmt, defaultSrc))
    else:
        res.update(msg="No file or image format allowed")
    return res
Пример #14
0
def upload():
    """上传逻辑:
    0. 判断是否登录,如果未登录则判断是否允许匿名上传
    1. 获取上传的文件,判断允许格式
        - 拦截下判断文件,如果为空,尝试获取body中提交的picbed
        - 如果picbed是合法base64,那么会返回Base64FileStorage类;
          如果picbed是合法url[图片],那么服务端会自动下载,返回ImgUrlFileStorage类;
          否则为空。
          PS: 允许DATA URI形式, eg: data:image/png;base64,the base64 of image
    2. 生成文件名、唯一sha值、上传目录等,选择图片存储的后端钩子(单一)
        - 存储图片的钩子目前版本仅一个,默认是up2local(如果禁用则保存失败)
        - 如果提交album参数会自动创建相册,否则归档到默认相册
    3. 解析钩子数据,钩子回调数据格式:{code=?, sender=hook_name, src=?}
        - 后端保存失败或无后端的情况都要立刻返回响应
    4. 此时保存图片成功,持久化存储到全局索引、用户索引
    5. 返回响应:{code:0, data={src=?, sender=success_saved_hook_name}}
        - 允许使用一些参数调整响应数据、格式
    """
    res = dict(code=1, msg=None)
    #: 文件域或base64上传字段
    FIELD_NAME = g.cfg.upload_field or "picbed"
    #: 匿名上传开关检测
    if not is_true(g.cfg.anonymous) and not g.signin:
        res.update(code=403, msg="Anonymous user is not sign in")
        return res
    #: 相册名称,可以是任意字符串
    album = (request.form.get("album")
             or getattr(g, "up_album", "")) if g.signin else 'anonymous'
    #: 实时获取后台配置中允许上传的后缀,如: jpg|jpeg|png
    allowed_suffix = partial(allowed_file,
                             suffix=parse_valid_verticaline(g.cfg.upload_exts))
    #: 尝试读取上传数据
    fp = request.files.get(FIELD_NAME)
    #: 当fp无效时尝试读取base64或url
    if not fp:
        picstrurl = request.form.get(FIELD_NAME)
        filename = request.form.get("filename")
        if picstrurl:
            if picstrurl.startswith("http://") or \
                    picstrurl.startswith("https://"):
                fp = ImgUrlFileStorage(picstrurl, filename).getObj
            else:
                try:
                    #: base64在部分场景发起http请求时,+可能会换成空格导致异常
                    fp = Base64FileStorage(picstrurl, filename)
                except ValueError as e:
                    logger.debug(e)
    if fp and allowed_suffix(fp.filename):
        try:
            g.rc.ping()
        except RedisError as e:
            logger.error(e, exc_info=True)
            res.update(code=2, msg="Program data storage service error")
            return res
        stream = fp.stream.read()
        suffix = splitext(fp.filename)[-1]
        filename = secure_filename(fp.filename)
        if "." not in filename:
            filename = "%s%s" % (generate_random(8), suffix)
        #: 根据文件名规则重定义图片名
        upload_file_rule = (
            g.userinfo.ucfg_upload_file_rule
            or g.cfg.upload_file_rule) if is_true(
                g.cfg.upload_rule_overridden) else g.cfg.upload_file_rule
        if upload_file_rule in ("time1", "time2", "time3"):
            filename = "%s%s" % (gen_rnd_filename(upload_file_rule), suffix)
        #: 上传文件位置前缀规则
        upload_path_rule = (
            g.userinfo.ucfg_upload_path_rule
            or g.cfg.upload_path_rule) if is_true(
                g.cfg.upload_rule_overridden) else g.cfg.upload_path_rule
        if upload_path_rule == 'date1':
            upload_path = get_today("%Y/%m/%d")
        elif upload_path_rule == 'date2':
            upload_path = get_today("%Y%m%d")
        else:
            upload_path = ''
        upload_path = join(g.userinfo.username or 'anonymous', upload_path)
        #: 定义文件名唯一索引
        sha = "sha1.%s.%s" % (get_current_timestamp(True), sha1(filename))
        #: 定义保存图片时仅使用某些钩子,如: up2local
        #: TODO 目前版本仅允许设置了一个,后续聚合
        includes = parse_valid_comma(g.cfg.upload_includes or 'up2local')
        if len(includes) > 1:
            includes = [choice(includes)]
        #: TODO 定义保存图片时排除某些钩子,如: up2local, up2other
        # excludes = parse_valid_comma(g.cfg.upload_excludes or '')
        #: 钩子返回结果(目前版本最终结果中应该最多只有1条数据)
        data = []

        #: 保存图片的钩子回调

        def callback(result):
            logger.info(result)
            if result["sender"] == "up2local":
                result["src"] = url_for("static",
                                        filename=join(UPLOAD_FOLDER,
                                                      upload_path, filename),
                                        _external=True)
            data.append(dfr(result))

        #: 调用钩子中upimg_save方法
        current_app.extensions["hookmanager"].call(
            _funcname="upimg_save",
            _callback=callback,
            _include=includes,
            filename=filename,
            stream=stream,
            upload_path=upload_path,
            local_basedir=join(current_app.root_path,
                               current_app.static_folder, UPLOAD_FOLDER))
        #: 判定后端存储全部失败时,上传失败
        if not data:
            res.update(code=1, msg="No valid backend storage service")
            return res
        if len(data) == len([i for i in data if i.get("code") != 0]):
            res.update(
                code=1,
                msg="All backend storage services failed to save pictures",
                errors={
                    i["sender"]: i["msg"]
                    for i in data if i.get("code") != 0
                },
            )
            return res
        #: 存储数据
        defaultSrc = data[0]["src"]
        pipe = g.rc.pipeline()
        pipe.sadd(rsp("index", "global"), sha)
        if g.signin and g.userinfo.username:
            pipe.sadd(rsp("index", "user", g.userinfo.username), sha)
        pipe.hmset(
            rsp("image", sha),
            dict(
                sha=sha,
                album=album,
                filename=filename,
                upload_path=upload_path,
                user=g.userinfo.username if g.signin else 'anonymous',
                ctime=get_current_timestamp(),
                status='enabled',  # disabled, deleted
                src=defaultSrc,
                sender=data[0]["sender"],
                senders=json.dumps(data),
                agent=request.form.get("origin",
                                       request.headers.get('User-Agent', '')),
                method=getUploadMethod(fp.__class__.__name__),
            ))
        try:
            pipe.execute()
        except RedisError as e:
            logger.error(e, exc_info=True)
            res.update(code=3, msg="Program data storage service error")
        else:
            res.update(
                code=0,
                filename=filename,
                sender=data[0]["sender"],
                api=url_for("api.shamgr", sha=sha, _external=True),
            )
            #: format指定图片地址的显示字段,默认src,可以用点号指定
            #: 比如data.src,那么返回格式{code, filename..., data:{src}, ...}
            #: 比如imgUrl,那么返回格式{code, filename..., imgUrl(=src), ...}
            fmt = request.form.get("format", request.args.get("format"))
            res.update(format_upload_src(fmt, defaultSrc))
    else:
        res.update(msg="No file or image format error")
    return res
Пример #15
0
def UploadBlogImage():
    editorType = request.args.get("editorType", "wangEditor")
    logger.sys.debug(request.files)
    f = request.files.get("WriteBlogImage") or request.files.get(
        "editormd-image-file")
    if f and allowed_file(f.filename):
        filename = secure_filename(gen_rnd_filename() + "." +
                                   f.filename.split('.')[-1])  #随机命名
        # 判断是否上传到又拍云还是保存到本地
        if PICBED['enable'] in ('true', 'True', True):
            success = True
            try:
                files = {
                    'picbed': (filename, f.stream.read(),
                               'image/%s' % filename.split(".")[-1])
                }
                resp = requests.post(
                    PICBED["api"],
                    files=files,
                    data=dict(album="blog"),
                    headers=dict(Authorization="LinkToken %s" %
                                 PICBED["LinkToken"]),
                    timeout=5).json()
                if not isinstance(resp, dict):
                    raise
            except Exception as e:
                success = False
                result = e.message
            else:
                if resp.get('code') == 0:
                    imgUrl = resp["src"]
                else:
                    success = False
                    result = resp["msg"]
            if success is False:
                if editorType == "wangEditor":
                    res = Response(result)
                    res.headers["ContentType"] = "text/html"
                else:
                    res = jsonify(message=result, success=0)
                    res.headers["ContentType"] = "application/json"
                res.headers["Charset"] = "utf-8"
                return res
        elif PLUGINS['UpYunStorage']['enable'] in ('true', 'True', True):
            imgUrl = "/EauDouce/blog/" + filename
            upres = UploadImage2Upyun(imgUrl, f.stream.read())
            imgUrl = PLUGINS['UpYunStorage']['dn'].strip("/") + imgUrl
            logger.sys.info(
                "Blog to Upyun file saved, its url is %s, result is %s" %
                (imgUrl, upres))
        else:
            if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER)
            f.save(os.path.join(UPLOAD_FOLDER, filename))
            imgUrl = request.url_root + IMAGE_FOLDER + filename
            logger.sys.info("Blog to local file saved in %s, its url is %s" %
                            (UPLOAD_FOLDER, imgUrl))
        #返回数据加上自定义头
        if editorType == "wangEditor":
            res = Response(imgUrl)
            res.headers["ContentType"] = "text/html"
        else:
            res = jsonify(url=imgUrl, message=None, success=1)
            res.headers["ContentType"] = "application/json"
    else:
        result = r"error|未成功获取文件或格式不允许,上传失败"
        if editorType == "wangEditor":
            res = Response(result)
            res.headers["ContentType"] = "text/html"
        else:
            res = jsonify(message=result, success=0)
            res.headers["ContentType"] = "application/json"
    res.headers["Charset"] = "utf-8"
    return res