import 'package:dio/dio.dart'; import 'package:flutter_picgo/api/github_api.dart'; import 'package:flutter_picgo/model/github_config.dart'; import 'package:flutter_picgo/model/uploaded.dart'; import 'package:flutter_picgo/resources/pb_type_keys.dart'; import 'package:flutter_picgo/utils/encrypt.dart'; import 'package:flutter_picgo/utils/image_upload.dart'; import 'package:flutter_picgo/utils/strings.dart'; import 'dart:io'; import 'dart:convert'; import 'package:path/path.dart' as path; import 'package:flutter_picgo/utils/strategy/image_upload_strategy.dart'; class GithubImageUpload implements ImageUploadStrategy { static const UPLOAD_COMMIT_MESSAGE = "Upload by Flutter-PicGo"; static const DELETE_COMMIT_MESSAGE = "Delete by Flutter-PicGo"; @override Future delete(Uploaded uploaded) async { String infoStr = await ImageUploadUtils.getUploadedItemInfo(uploaded.id); GithubUploadedInfo info; try { info = GithubUploadedInfo.fromJson(json.decode(infoStr)); } catch (e) {} if (info != null) { String realUrl = path.joinAll([ 'repos', info.ownerrepo, 'contents', info.path ]); await GithubApi.deleteContent(realUrl, { "message": DELETE_COMMIT_MESSAGE, "sha": info.sha, "branch": info.branch }); } return uploaded; } @override Future upload(File file, String renameImage) async { try { String configStr = await ImageUploadUtils.getPBConfig(PBTypeKeys.github); if (!isBlank(configStr)) { GithubConfig config = GithubConfig.fromJson(json.decode(configStr)); String realUrl = path.joinAll([ 'repos', config.repo, 'contents', config.path, renameImage ]); var result = await GithubApi.putContent(realUrl, { "message": UPLOAD_COMMIT_MESSAGE, "content": await EncryptUtils.image2Base64(file.path), "branch": config.branch }); String imagePath = result["content"]["path"]; String downloadUrl = result["content"]["download_url"]; String sha = result["content"]["sha"]; String imageUrl = isBlank(config.customUrl) ? downloadUrl : '${path.joinAll([config.customUrl, imagePath])}'; var uploadedItem = Uploaded(-1, imageUrl, PBTypeKeys.github, info: json.encode(GithubUploadedInfo( path: imagePath, sha: sha, branch: config.branch, ownerrepo: config.repo))); await ImageUploadUtils.saveUploadedItem(uploadedItem); return uploadedItem; } else { throw GithubError(error: '读取配置文件错误!请重试'); } } on DioError catch (e) { if (e.type == DioErrorType.RESPONSE && e.error.toString().indexOf('422') > 0) { throw GithubError(error: '文件已存在!'); } else { throw e; } } } } /// GithubError describes the error info when request failed. class GithubError implements Exception { GithubError({ this.error, }); dynamic error; String get message => (error?.toString() ?? ''); @override String toString() { var msg = 'GithubError $message'; if (error is Error) { msg += '\n${error.stackTrace}'; } return msg; } } class GithubUploadedInfo { String sha; String branch; String path; String ownerrepo; GithubUploadedInfo({this.sha, this.branch, this.path, this.ownerrepo}); GithubUploadedInfo.fromJson(Map json) { sha = json['sha']; branch = json['branch']; path = json['path']; ownerrepo = json['ownerrepo']; } Map toJson() { final Map data = new Map(); data['sha'] = this.sha; data['branch'] = this.branch; data['path'] = this.path; data['ownerrepo'] = this.ownerrepo; return data; } }