PicHoro 是一款基于 Flutter 的手机端云存储平台/图床管理和文件上传/下载工具,最新版本 V2.4.0。
- 与 PicGo/PicList 配置互通,可直接扫码导入
- 支持云存储/图床/云服务器平台和网盘管理(通过 Alist)
- 提供文件上传、下载管理及多格式链接分享功能
支持多种图片/PDF/文本文件/音视频的在线预览和播放,具体支持的格式请查看支持的格式列表。
桌面端推荐:如果您需要桌面端图床管理,推荐使用 PicList
- 兰空图床V2
- SM.MS
- Github
- Imgur
- 七牛云存储
- 腾讯云COS V5
- 阿里云OSS
- 又拍云存储
- FTP-SSH/SFTP
- 兼容S3 API接口的平台
- Alist V3
- WebDav
- 云存储/图床管理 - 新建/删除/修改存储桶,创建/删除目录和文件,上传和下载文件和照片等
- 网盘管理 - 通过 Alist V3 或 WebDav 管理多种网盘
- 图片压缩 - 支持压缩为 webp/jpg/png 格式
- 多格式文件预览 - 包括图片/PDF/文本文件/音视频等
- SSH/SFTP支持 - 可视化管理文件,内置 SSH 终端可直接管理云服务器
- PicGo兼容性 - 支持扫描二维码将 PicGo(v2.3.0-beta.2 以上版本)配置文件直接导入 PicHoro
- 每种图床最多支持 26 个备用配置,可快速切换
- 连续上传模式,相机拍照后自动上传并返回拍照页面
- 支持导入剪贴板中的网络图片链接,换行符分割可批量导入
- 上传图片后自动复制链接到剪贴板
- 自定义复制到剪贴板的链接格式,占位符与 PicGo 一致
- 多种文件重命名方式(时间戳、随机字符串和自定义重命名)
- 相册分图床显示,支持多选管理,复制多张图片链接或删除
- 支持导出配置至剪贴板(与 PicGo 配置文件格式相同)
- 查看和导出软件日志,快捷查找问题和报告 bug
平台 | 图片 | 文本文件 | 视频 | |
---|---|---|---|---|
Alist | ✅ | ✅ | ✅ | ✅ |
阿里云 | ✅ | ✅ | ✅ | ✅ |
S3 | ✅ | ✅ | ✅ | ✅ |
腾讯云 | ✅ | ✅ | ✅ | ✅ |
又拍云 | ✅ | ✅ | ✅ | ✅ |
七牛云 | ✅ | ✅ | ✅ | ✅ |
WebDav | ✅ | ✅ | ✅ | ✅ |
FTP | ✅ | ❌ | ✅ | ❌ |
Github | ✅ | ❌ | ✅ | ❌ |
Imgur | ✅ | ❌ | ❌ | ✅ |
兰空 | ✅ | ❌ | ❌ | ❌ |
SM.MS | ✅ | ❌ | ❌ | ❌ |
- Github 下载: Github release
- 官网下载: 最新版本 V2.4.0
目前暂无 iOS 版本。如果您有兴趣帮助开发 iOS 版本,请联系我们提供技术支持。
7ddc751ff2b354b4e9ab7729946ec7aa.mp4
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
详细更新日志请查看更新日志
- 与 AList 3.35 版本保持同步
alist
图床现在支持设置管理员 tokensm.ms
图床上传重复图片时不再判定为失败- S3 兼容平台支持带端口号的 endpoint
- S3 兼容平台支持设置是否启用 SSL 连接和 S3 path style
- 优化图床导入,支持 PicList 内置 AList、兰空图床、ftp 图床、WebDAV 图床及 alist 图床插件配置
- 优化文件 mime 类型判断,兼容更多文件类型并默认使用
application/octet-stream
- 重命名占位符
{m}
和{d}
固定为两位数字,如01
、02
- 新增重命名占位符:
{h}
(小时)、{i}
(分钟)、{s}
(秒)、{ms}
(毫秒)、{str-num}
- 默认自定义重命名格式修改为
{Y}{m}{d}{h}{i}{ms}
,与 PicGo 一致 - 默认自定义链接格式修改为

- 设置图床配置时自动去除开头和结尾多余空格
- alist 备用设置中无法设置网址路径的问题
- alist 设置了网址路径时返回地址多了一个 '/' 的问题
- alist 返回链接是平台直链而非 alist 专用网址的问题
- 特定情况下
ftp
图床返回链接错误的问题 - ftp 图床设置页面打开错误的问题
- 导入
imgur
配置时错误保存到smms
的问题 - 关闭自动复制链接后仍然会复制到剪贴板的问题
- 开发进度: 查看 Projects
- 讨论交流: 加入 Github 讨论区
- 问题反馈: 在 Github Issues 提出
Telegram 交流群:
克隆本项目后,请同时克隆以下项目到同级目录:
git clone https://github.com/Kuingsmile/flutterdep
- 准备环境: 安装 Android Studio、Android SDK 21+ 和 Flutter 3.13
- 克隆仓库:
git clone https://github.com/Kuingsmile/PicHoro.git
- Windows 用户推荐使用 VSCode 编辑和调试代码
兰空图床相册 ID 参数生效条件:
- 基于付费企业版兰空图床搭建
- 开源免费版需修改源代码文件
/app/Services/ImageService.php
:
// 原代码
if ($albumId = $user->configs->get(UserConfigKey::DefaultAlbum)) {
if ($user->albums()->where('id', $albumId)->exists()) {
$image->album_id = $albumId;
}
}
// 修改后
if ($request->has('album_id')) {
$image->album_id = $request->input('album_id');
} else {
if ($albumId = $user->configs->get(UserConfigKey::DefaultAlbum)) {
if ($user->albums()->where('id', $albumId)->exists()) {
$image->album_id = $albumId;
}
}
}
本 APP 使用的部分依赖包需要手动修改:
包含在 https://github.com/Kuingsmile/flutterdep
中,无需手动修改。
queries['maxKeys']
修改为queries['max-keys']
- 添加导入
import 'package:xml2json/xml2json.dart';
- 如下修改
listBuckets
函数
Future<List<Bucket>> listBuckets() async {
final resp = await _client.request(
method: 'GET',
region: region ?? 'us-east-1',
);
final myTransformer = Xml2Json();
myTransformer.parse(resp.body);
Map responseMap = json.decode(myTransformer.toParker());
List<Bucket> buckets = [];
if (responseMap['ListAllMyBucketsResult'] == null ||
responseMap['ListAllMyBucketsResult']['Buckets'] == null ||
responseMap['ListAllMyBucketsResult']['Buckets']['Bucket'] == null ||
responseMap['ListAllMyBucketsResult']['Buckets']['Bucket'].length ==
0) {
return buckets;
}
if (responseMap['ListAllMyBucketsResult']['Buckets']['Bucket'] is! List) {
buckets.add(Bucket(
DateTime.parse(responseMap['ListAllMyBucketsResult']['Buckets']
['Bucket']['CreationDate']),
responseMap['ListAllMyBucketsResult']['Buckets']['Bucket']['Name']));
return buckets;
}
for (var bucket in responseMap['ListAllMyBucketsResult']['Buckets']
['Bucket']) {
buckets
.add(Bucket(DateTime.parse(bucket['CreationDate']), bucket['Name']));
}
return buckets;
}
文件路径示例: "D:\flutter\.pub-cache\hosted\pub.flutter-io.cn\chewie-1.3.6\lib\src\player_with_controls.dart"
修改第 86 行:
return Container(
color:Colors.black,
child:Center(
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: AspectRatio(
aspectRatio: calculateAspectRatio(context),
child: buildPlayerWithControls(chewieController, context),
),
)),
);
使用以下命令构建:
flutter build apk --release
构建成功后,在 build\app\outputs\flutter-apk\release
生成 app-release.apk
文件。
注意: 请设置
minifyEnabled false
和shrinkResources false
,否则打包后可能闪退。
Copyright (c) 2022-present, Kuingsmile