photos
将图片保存到系统照片图库,以及拍照和录像。
photos.save
将一张图片保存到系统照片图库。Photos 完成保存后 Promise resolve;授权、下载、验证或保存失败时 Promise reject。
type PhotoSaveOptions =
| {
url: string | URL;
headers?: Readonly<Record<string, string>>;
filename?: string;
}
| {
data: Blob | ArrayBuffer | ArrayBufferView;
filename?: string;
};
function photos.save(options: PhotoSaveOptions): Promise<void>;options 必须指定一种图片来源:
| 属性 | 类型 | 说明 |
|---|---|---|
url | string | URL | HTTP 或 HTTPS 图片地址。 |
headers | Record<string, string> | URL 请求使用的可选请求头。 |
data | Blob | ArrayBuffer | ArrayBufferView | 脚本已经持有的图片字节。File 和 Node.js Buffer 均由这些类型覆盖。 |
filename | string | 保存到图库的可选原始文件名。 |
第一次保存时,系统可能显示照片图库“仅添加”权限提示。API 可在 app、action 和 widget 脚本中调用,系统决定当前环境能否完成 Photos 访问。
成功保存后返回的 Promise resolve,且没有返回值。url 和 data 必须二选一;空数据、非法 URL、非法请求头及原生处理错误会使 Promise reject。
保存 URL 图片
import { photos } from "onescript";
await photos.save({
url: "https://example.com/photos/original.heic",
filename: "original.heic"
});需要身份认证时可以显式传入请求头:
await photos.save({
url: "https://api.example.com/private/photo.jpg",
headers: {
Authorization: `Bearer ${token}`
}
});URL 下载使用 GET 和独立的临时会话。请求不会读取或写入 App 的 Cookie、缓存和已保存 HTTP 凭据。通过 headers 显式传入的 Cookie 仅用于当前请求及同源重定向;跨源重定向会移除 Authorization、Cookie 和 Proxy-Authorization。
保存图片数据
const response = await fetch("https://example.com/generated.png");
await photos.save({
data: await response.blob(),
filename: "generated.png"
});省略 filename 时,File 会提供自身文件名:
await photos.save({ data: imageFile });Node.js Buffer 可以直接传入:
import { readFile } from "node:fs/promises";
import { photos } from "onescript";
const data = await readFile("images/result.png");
await photos.save({ data, filename: "result.png" });原始文件名按以下顺序推导:显式 filename、File.name、最终 URL 的路径末段、Photos 自动生成。
大图片
URL 响应会直接下载到临时文件。内存数据按 512 KiB 分块传输,每条 Bridge JSON 消息保持在约 700 KiB 以内,并在 Photos 导入前持续写入临时文件。OneScript 不设置固定的图片总大小上限,实际限制由可用存储空间、脚本环境生命周期和 Photos 决定;脚本取消、退出或异常结束时,未完成的下载和临时文件会被清理。
错误处理
使用 try/catch 处理错误。原生错误使用稳定前缀,包括 PHOTO_PERMISSION_DENIED、PHOTO_DOWNLOAD_FAILED、PHOTO_TRANSFER_FAILED、PHOTO_INVALID_IMAGE 和 PHOTO_SAVE_FAILED。
try {
await photos.save({ data: imageData, filename: "photo.png" });
} catch (error) {
console.error("保存图片失败:", error);
}photos.takePhoto
打开系统相机,以 File 返回拍摄的照片。用户取消时 Promise resolve 为 null。
type CameraDevice = "back" | "front";
interface TakePhotoOptions {
device?: CameraDevice;
}
function photos.takePhoto(options?: TakePhotoOptions): Promise<File | null>;| 属性 | 类型 | 说明 |
|---|---|---|
device | "back" | "front" | 使用的摄像头,默认 "back"。 |
返回的 File 是 JPEG(image/jpeg),名称为 IMG_yyyyMMdd_HHmmss.jpg,lastModified 为用户确认照片的时间。像素已按拍摄时的方向转正,不包含 EXIF、位置等元数据。
import { photos } from "onescript";
const photo = await photos.takePhoto();
if (photo) {
await photos.save({ data: photo });
}文件可以直接上传:
const photo = await photos.takePhoto({ device: "front" });
if (photo) {
const form = new FormData();
form.append("avatar", photo);
await fetch("https://api.example.com/avatar", { method: "POST", body: form });
}photos.recordVideo
以录像模式打开系统相机,返回录好的文件的绝对路径。用户取消时 Promise resolve 为 null。
interface RecordVideoOptions {
device?: CameraDevice;
maxDuration?: number;
quality?: "high" | "medium" | "low";
}
function photos.recordVideo(options?: RecordVideoOptions): Promise<string | null>;| 属性 | 类型 | 说明 |
|---|---|---|
device | "back" | "front" | 使用的摄像头,默认 "back"。 |
maxDuration | number | 最长录制时间(秒),到时自动停止。必须是有限的正数。 |
quality | "high" | "medium" | "low" | 录制质量,默认 "high"。 |
视频按录制结果原样保存为 QuickTime 格式(.mov),名称为 VID_yyyyMMdd_HHmmss.mov。视频可能很大,所以保留在磁盘上,只返回路径。
文件存放在本次运行专属的临时目录中,脚本结束时删除。要保留视频,用 fs.rename 把它移走,例如移到项目的持久化数据目录 os.homedir():
import { rename } from "node:fs/promises";
import os from "node:os";
import { join } from "node:path";
import { photos } from "onescript";
const video = await photos.recordVideo({ maxDuration: 30 });
if (video) {
await rename(video, join(os.homedir(), "clip.mov"));
}相机的可用范围与权限
相机只在 OneScript App 运行的脚本中可用。Widget 没有界面,iOS 也不允许 App 扩展使用相机,因此在 widget 和 action 脚本中调用会以 PHOTO_CAMERA_UNAVAILABLE reject。设备上没有请求的摄像头时(包括模拟器)也会报告同样的错误。
第一次拍照时系统会显示相机权限提示;第一次录像时还会请求麦克风权限,用于录制声音。同一时间只能打开一个相机界面。相机打开期间脚本停止运行时,相机会关闭,Promise reject。
错误
| 错误 | 原因 |
|---|---|
PHOTO_CAMERA_UNAVAILABLE | 脚本不在 App 中运行,或请求的摄像头不可用。 |
PHOTO_CAMERA_PERMISSION_DENIED | 相机或麦克风权限被拒绝,消息中会注明是哪一个。 |
PHOTO_CAPTURE_BUSY | 已经有一个相机界面处于打开状态。 |
PHOTO_CAPTURE_FAILED | 照片或视频处理失败。 |
try {
const photo = await photos.takePhoto();
} catch (error) {
console.error("拍照失败:", error);
}How is this guide?
最后更新于