跳到主要内容
版本:v8

将照片保存到文件系统

我们现在能够拍摄多张照片并在应用的第二个标签页的相册中显示。但是,这些照片目前并未永久存储,因此当应用关闭时,它们将被删除。

Filesystem API

幸运的是,将它们保存到文件系统只需几个步骤。首先在 PhotoService 类中创建一个新的类方法 savePicture()。我们传入 photo 对象,它代表新拍摄的设备照片:

import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
// CHANGE: Add import
import type { Photo } from '@capacitor/camera';

@Injectable({
providedIn: 'root',
})
export class PhotoService {
// ...existing code...

// CHANGE: Add the `savePicture()` method
private async savePicture(photo: Photo) {
return {
filepath: 'soon...',
webviewPath: 'soon...',
};
}
}

export interface UserPhoto {
filepath: string;
webviewPath?: string;
}

我们可以立即在 addNewToGallery() 中使用这个新方法。

import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';

@Injectable({
providedIn: 'root',
})
export class PhotoService {
public photos: UserPhoto[] = [];

// CHANGE: Update the `addNewToGallery()` method
public async addNewToGallery() {
// Take a photo
const capturedPhoto = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 100,
});

// CHANGE: Add `savedImageFile`
// Save the picture and add it to photo collection
const savedImageFile = await this.savePicture(capturedPhoto);

// CHANGE: Update argument to unshift array method
this.photos.unshift(savedImageFile);
}

private async savePicture(photo: Photo) {
return {
filepath: 'soon...',
webviewPath: 'soon...',
};
}
}

export interface UserPhoto {
filepath: string;
webviewPath?: string;
}

我们将使用 Capacitor Filesystem API 来保存照片。首先,将照片转换为 base64 格式。

然后,将数据传递给 Filesystem 的 writeFile 方法。回想一下,我们通过将图像的源路径 (src) 设置为 webviewPath 属性来显示照片。因此,设置 webviewPath 并返回新的 Photo 对象。

现在,创建一个新的辅助方法 convertBlobToBase64(),以实现 Web 上运行所需的逻辑。

import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import type { Photo } from '@capacitor/camera';
// CHANGE: Add import
import { Filesystem, Directory } from '@capacitor/filesystem';

@Injectable({
providedIn: 'root',
})
export class PhotoService {
// ...existing code...

// CHANGE: Update the `savePicture()` method
private async savePicture(photo: Photo) {
// Fetch the photo, read as a blob, then convert to base64 format
const response = await fetch(photo.webPath!);
const blob = await response.blob();
const base64Data = (await this.convertBlobToBase64(blob)) as string;

// Write the file to the data directory
const fileName = Date.now() + '.jpeg';
const savedFile = await Filesystem.writeFile({
path: fileName,
data: base64Data,
directory: Directory.Data,
});

// Use webPath to display the new image instead of base64 since it's
// already loaded into memory
return {
filepath: fileName,
webviewPath: photo.webPath,
};
}

// CHANGE: Add the `convertBlobToBase64` method
private convertBlobToBase64(blob: Blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = reject;
reader.onload = () => {
resolve(reader.result);
};
reader.readAsDataURL(blob);
});
}
}

export interface UserPhoto {
filepath: string;
webviewPath?: string;
}

photo.service.ts 现在应该如下所示:

import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import type { Photo } from '@capacitor/camera';
import { Filesystem, Directory } from '@capacitor/filesystem';

@Injectable({
providedIn: 'root',
})
export class PhotoService {
public photos: UserPhoto[] = [];

public async addNewToGallery() {
// Take a photo
const capturedPhoto = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 100,
});

// Save the picture and add it to photo collection
const savedImageFile = await this.savePicture(capturedPhoto);

this.photos.unshift(savedImageFile);
}

private async savePicture(photo: Photo) {
// Fetch the photo, read as a blob, then convert to base64 format
const response = await fetch(photo.webPath!);
const blob = await response.blob();
const base64Data = (await this.convertBlobToBase64(blob)) as string;

// Write the file to the data directory
const fileName = Date.now() + '.jpeg';
const savedFile = await Filesystem.writeFile({
path: fileName,
data: base64Data,
directory: Directory.Data,
});

// Use webPath to display the new image instead of base64 since it's
// already loaded into memory
return {
filepath: fileName,
webviewPath: photo.webPath,
};
}

private convertBlobToBase64(blob: Blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = reject;
reader.onload = () => {
resolve(reader.result);
};
reader.readAsDataURL(blob);
});
}
}

export interface UserPhoto {
filepath: string;
webviewPath?: string;
}

在 Web 上将相机照片获取为 base64 格式似乎比在移动端要复杂一些。实际上,我们只是使用了内置的 Web API:fetch() 作为一种将文件读取为 blob 格式的简洁方法,然后使用 FileReader 的 readAsDataURL() 将照片 blob 转换为 base64。

就是这样!每次拍摄新照片时,它现在都会自动保存到文件系统。接下来,我们将加载并显示已保存的图像。