def defaultUserPath(aUserId): """ 用户默认路径 user default path """ global __gDefaultUserPath if __gDefaultUserPath == "*": __gDefaultUserPath = AppConfig().defaultUserPath strPathName = "{}".format(aUserId) defPath = os.path.join(__gDefaultUserPath, strPathName) if not os.path.isdir(defPath): log.logObject().info("create path: {}".format(defPath)) os.makedirs(defPath) return defPath
def sendFile(aStrFileName, aErrorStatusCode=200): """发送文件到客户端,支持单 Range 请求 :aStrFileName: 文件名称 :returns: Response """ if not os.path.isfile(aStrFileName): log.logObject().error("找不到文件=%s" % aStrFileName) return buildErrorResponseData(kCmdUserError_NotResource, statusCode=aErrorStatusCode) try: httpHeaderRange = request.headers.get("Range") r = http.parse_range_header(httpHeaderRange) bHasRange = r is not None and len( r.ranges) == 1 and r.ranges[0][0] is not None except Exception as e: bHasRange = False #发送整个文件 if not bHasRange: return send_file(aStrFileName) #发送部分文件 nFileSize = os.path.getsize(aStrFileName) beginPos, stopPos = r.range_for_length(nFileSize) with open(aStrFileName, "rb") as f: f.seek(beginPos) byteContens = f.read(stopPos - beginPos) strMimeType = mimetypes.guess_type(aStrFileName)[0] if strMimeType is None: strMimeType = "application/octet-stream" resp = Response(byteContens, 206, mimetype=strMimeType, headers={ "Content-Range": r.make_content_range(nFileSize), "Accept-Ranges": r.units, "Etag": "%d" % nFileSize }) return resp
def makeUser(self, aUserName, aPassword): "若插入不成功,则判断修改密码,返回ID" curTime = unit.getTimeInt() fieldValues = { "name": aUserName, "password": aPassword, "createTime": curTime, "lastLoginDate": curTime, "lastModifyTime": curTime } nId = self.insert(_kUserTableName, fieldValues) if nId is None: #插入不成功,正常情况是数据已经存在 row = self.select(_kUserTableName, {"name": aUserName}) if row is None: log.logObject().log(logging.ERROR, "无法创建用户 %s" % aUserName) return None nId = row[kUserFieldId] if aPassword and len( aPassword) > 0 and row[kUserFieldPassword] != aPassword: self.update(_kUserTableName, {"id": nId}, {"password": aPassword}) return nId
def checkApiParamWithRequestValues(aNeedLogin, aParams, aRequestValues): """判断Api参数信息是否正确 :aNeedLogin: 是否需要登陆才能使用 :aParams: API请求的参数,是一个list, 元素为dict: 有以下可用内容 name: 请求参数名; checkfunc: 从request获取到的数据后进行检查,返回None表示此参数不正确 default: 当提供此值时,说明这是个可选参数,当参数不正确或没有时,将使用此值代替 元素为string: 表示name :returns: (bSuccess, 成功时: loginInfo(当aNeedLogin时,否则为None), {key, value} 失败时: response, realStatusCode(实际上的错误码) """ # 判断是否需要登陆, 失败实际Code: 403 loginInfo = None if aNeedLogin: key = session.get(defines.kSessionUserKey) loginInfo = LoginInfo.GetObject(key) if loginInfo is None: return False, buildErrorResponseData(kCmdUserError_NeedLogin), 403 # 参数判断, 失败实际Code: 416 try: result = [] result.append(True) result.append(loginInfo) params = {} # begin for for item in aParams: if isinstance(item, str): key = item bHasDefaultValue = False bHasCheckFunc = False else: key = item["name"] bHasDefaultValue = "default" in item.keys() defaultValue = item["default"] if bHasDefaultValue else None bHasCheckFunc = "checkfunc" in item.keys() checkFunc = item["checkfunc"] if bHasCheckFunc else None value = aRequestValues.get(key) if bHasCheckFunc: try: value = checkFunc(value) except Exception as e: value = None bParamOK = value != None if not bParamOK and bHasDefaultValue: value = defaultValue bParamOK = True if not bParamOK: log.logObject().info("parse not ok: {}, value: {}".format( item, value)) return False, buildErrorResponseData(kCmdUserError_Param), 416 params[key] = value # end for result.append(params) return result except Exception as e: log.logObject().error("parse param error: {}".format(e)) return False, buildErrorResponseData(kCmdUserError_Param), 417
def appUploadFile(): "上传文件" # print(request.args) result = responseHelp.checkApiParamWithRequestValues(True, ( {"name": "id", "checkfunc": unit.checkParamForInt}, {"name": "obp", "checkfunc": unit.checkParamForInt, "default": 0}, {"name": "tbp", "checkfunc": unit.checkParamForInt, "default": 0}, {"name": "sbp", "checkfunc": unit.checkParamForInt, "default": 0}, {"name": "cm", "default": None} ), request.args) if not result[kParamForResult]: return result[kParamForErrorResponse] loginInfo = result[kParamForLoginInfo] param = result[kParamForRequestParams] nFileId = param["id"] db = _getDbManager() fileRow = db.getFileByIdAndRootIds(nFileId, loginInfo.rootIdsString) if not fileRow: return responseHelp.buildErrorResponseData(responseHelp.kCmdUserError_Param) upFileInfos = {} orgFullFileName = None upFileNames = {} def _myUploadFileStreamFactory(aTotalContentLength, aContentType, aFileName, aContentLength): "生成文件进入写入操作" strFullFileName = None nBeginPos = 0 strDbFiledName = None if aFileName == "origin": #处理R原始文件 catalogRow = db.getCatalogByIdAndRootIds(fileRow[dataManager.kFileFieldRealCatalogId], loginInfo.rootIdsString) if catalogRow: strFullFileName = os.path.join(catalogRow[dataManager.kCatalogFieldPath], fileRow[dataManager.kFileFieldFileName]) nBeginPos = param["obp"] strDbFiledName = "statusForOrigin" nonlocal orgFullFileName orgFullFileName = strFullFileName elif aFileName == "thumb": #小缩略图 strFullFileName = unit.getFileThumbFullFileName(fileRow[dataManager.kFileFieldRealCatalogId], nFileId, 0) nBeginPos = param["tbp"] strDbFiledName = "statusForThumb" elif aFileName == "screen": #大缩略图 strFullFileName = unit.getFileThumbFullFileName(fileRow[dataManager.kFileFieldRealCatalogId], nFileId, 0) nBeginPos = param["sbp"] strDbFiledName = "statusForScreen" if not strFullFileName: raise RuntimeError("filename is error") # 判断文件的大小,与传入参数进行对比,若传入文件大小过大,则直接报错.否则根据传入参数进行写操作 nCurFileSize = os.stat(strFullFileName).st_size if os.path.isfile(strFullFileName) else 0 if nBeginPos > nCurFileSize: raise RuntimeError("begin position is error!") upFileInfos[strDbFiledName] = defines.kFileStatusFromUploaded upFileNames[aFileName] = strFullFileName # print("will open file: ", strFullFileName, "; beginPos: ", nBeginPos) f = open(strFullFileName, "a+b") f.truncate(nBeginPos) f.seek(0, os.SEEK_END) return f # 开始接收文件内容 try: stream,form,files = werkzeug.formparser.parse_form_data(request.environ, stream_factory = _myUploadFileStreamFactory, silent = False) except Exception as e: for key in upFileInfos.keys(): upFileInfos[key] = defines.kFileStatusFromUploading db.updateFile(nFileId, upFileInfos, loginInfo.rootIdsString) log.logObject().error(e) return responseHelp.buildErrorResponseData(responseHelp.kCmdUserError_Param) # 更新数据库 if orgFullFileName: upFileInfos["size"] = os.stat(orgFullFileName).st_size db.updateFile(nFileId, upFileInfos, loginInfo.rootIdsString) # 生成返回数据 fileRow = db.getFileByIdAndRootIds(nFileId, loginInfo.rootIdsString) funcForIdRelatePath = lambda : db.getCatalogIdRelatePathInfo(fileRow[dataManager.kFileFieldRealCatalogId]) fileInfo = dataManager.buildFileInfo(fileRow, funcForIdRelatePath) result = {"fileInfo": fileInfo} #写入检验值 strCm = param["cm"] if strCm: strCm = strCm.lower() bSha1 = strCm == "sha1" bMd5 = not bSha1 and strCm == "md5" if bSha1 or bMd5: check = {} for key, filename in upFileNames.items(): check[key] = unit.SHA1FileWithName(filename) if bSha1 else unit.MD5FileWithName(filename) result["check"] = check return responseHelp.buildSuccessResponseData(result)