返回
不用一键,也能上传图片
开发工具
2024-01-28 12:01:58
一直以来用的都是 MarkEditor 写作,它有一个比较重要的功能:能自动将拷贝到编辑器中的截图同步到图床,这样如果要将文章导出发到其他平台,由于本地的图片在导出后自动转成了链接,所以无需担心图片在其他平台的识别问题。
但是最近发现文章同步到掘金或 CSDN 这些平台时,这些平台并不会解析 MarkEditor 生成的图片链接。
虽然可以手动将图片上传到这些平台,但这样一来图片的管理就变得复杂了,一方面需要先将图片下载到本地,然后上传到图床,最后还要在文章中修改图片链接;另一方面,如果想要在多篇文章中引用同一张图片,还需要手动在每篇文章中上传图片。
为了解决这个问题,我写了一个 Alfred 工作流,可以一键将图片上传到图床,并且自动将图片链接复制到剪贴板。
使用方法:
- 下载并安装 Alfred。
- 下载并导入工作流:https://github.com/hjiang/alfred-workflows/blob/master/UploadImage.alfredworkflow。
- 在 Alfred 中输入 "upimg",然后选择 "Upload Image" 工作流。
- 将图片拖放到 Alfred 中。
- 工作流会自动将图片上传到图床,并将图片链接复制到剪贴板。
注意:
-
工作流需要配置图床信息,包括图床地址、API 密钥和 Bucket 名称。
-
工作流支持以下图床:
- 七牛云
- 阿里云 OSS
- 又拍云
- 腾讯云 COS
- 华为云 OBS
-
工作流使用 Rust 语言编写,需要安装 Rust 编译器。
结语:
这个 Alfred 工作流可以极大地简化图片上传的过程,对于经常在多个平台发布文章的用户来说非常有用。
示例代码:
use alfred::workflow::{Argument, Item, Output, Workflow};
use clap::{App, Arg};
use reqwest::header::HeaderMap;
use reqwest::Url;
use std::env;
use std::fs;
use std::io::Read;
use std::path::PathBuf;
fn main() {
let args = App::new("Upload Image")
.arg(
Arg::with_name("IMAGE_PATH")
.help("Path to the image file")
.required(true),
)
.arg(
Arg::with_name("TUPU_ACCESS_KEY")
.help("Tupu access key")
.required(true),
)
.arg(
Arg::with_name("TUPU_SECRET_KEY")
.help("Tupu secret key")
.required(true),
)
.arg(
Arg::with_name("TUPU_BUCKET_NAME")
.help("Tupu bucket name")
.required(true),
)
.arg(
Arg::with_name("TUPU_BASE_URL")
.help("Tupu base URL")
.required(true),
)
.get_matches();
let image_path = args.value_of("IMAGE_PATH").unwrap();
let access_key = args.value_of("TUPU_ACCESS_KEY").unwrap();
let secret_key = args.value_of("TUPU_SECRET_KEY").unwrap();
let bucket_name = args.value_of("TUPU_BUCKET_NAME").unwrap();
let base_url = args.value_of("TUPU_BASE_URL").unwrap();
let mut workflow = Workflow::new();
let mut file = fs::File::open(image_path).unwrap();
let mut bytes = Vec::new();
file.read_to_end(&mut bytes).unwrap();
let mut headers = HeaderMap::new();
headers.insert("access-key", access_key.parse().unwrap());
headers.insert("secret-key", secret_key.parse().unwrap());
headers.insert("bucket-name", bucket_name.parse().unwrap());
let url = format!("{}/file", base_url);
let client = reqwest::Client::new();
let response = client
.post(url)
.headers(headers)
.body(bytes)
.send()
.unwrap();
if response.status().is_success() {
let json = response.json::<serde_json::Value>().unwrap();
let image_url = json["result"]["url"].as_str().unwrap();
workflow.add_item(
Item::new("Upload Image")
.subtitle(image_url)
.arg(Argument::new("copy").with_valid_items(vec![image_url])),
);
} else {
workflow.add_item(Item::new("Upload Image Failed"));
}
print!("{}", workflow.output().unwrap());
}