angular前台调用相册和拍照

文章讲述了如何在Angular应用中使用Capacitor的Camera插件获取照片,包括设置质量、格式和获取Base64或本地URI,以及处理Android13上权限问题。同时介绍了处理Blob和Base64数据的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//下载依赖, 本文使用版本
"peerDependencies": {
  "@capacitor/camera": "^4.1.0", 
  "@angular/platform-browser": "^14.2.0",
  "@angular/platform-browser-dynamic": "^14.2.0"
}

//引入组件
import { Camera, CameraResultType } from '@capacitor/camera';
import { DomSanitizer } from '@angular/platform-browser';

constructor(public sanitizer: DomSanitizer){}

//异步的方法, 当触发该方法时,调用相机或相册,获取选中图片的数据 blob流 或者 base64 
async selectFile() {
  //调用Camera插件的 getphoto方法 实现调用手机相册和相机的功能, 电脑上会调用文件夹
  // quality: 定义保存图片的质量,取值范围为[0,100],100表示质量最高
  // destinationType: 选择返回数据的格式,取值为三个常量之一 
    //  Camera.DestinationType.DATA_URL     表示返回图片作为base64编码
    //  Camera.DestinationType.FILE_URI     返回影像档的 URI
    //  Camera.DestinationType.NATIVE_URI   返回图像本机URI
  // allowEdit: 取值范围为true false 设置在选择图片进行操作之前是否对其进行简单的编辑(Android系统会忽略此属性)    
  // encodingType: 用于设置返回文件的类型,有一下几个常量可用  
    //  Camera.EncodingType.JPEG 表示返回JPEG编码的图片
    //  Camera.EncodingType.PNG 表示返回PNG编码的图片
  // targetWidth: 用于定义缩放图片的宽度,以像素为单位。必须和targetHeight配合使用
  // targetHeight:  用于定义缩放图片的高度,以像素为单位。必须和targetWidth 配合使用
  // saveToPhotoAlbum: 取值范围为true false 用于决定是否在捕捉图片之后放入相册

  //本文中用到的 resultType  等于destinationType

  const image = await Camera.getPhoto({
    quality: 90,
    allowEditing: true,
    resultType: CameraResultType.Uri
  });

  //获取返回的路径  eg:"blob:http://localhost:8100/8e25daf2-9a9e-43db-9331-c26e63161552"  可使用该路径在页面展示图片,要去掉blob: 的字符,不然安全策略无法通过
  let selectedFileUri = image.webPath;
  //调用方法,根据blob路径获取blob数据
  let fileBlob = this.createBlobFromUri(image.webPath);
  const imgtype = (await fileBlob).type;//获取文件类型 eg:"image/png"
  const imgtypeLast = imgtype.substring(imgtype.lastIndexOf('/') + 1, imgtype.length);//过滤 eg:'png'
  let fileType = imgtypeLast;
  const num = 1024.00;
  let imgSize = (await fileBlob).size;//获取图片大小  eg:3326616   大小单位为KB
  imgSize = (imgSize / Math.pow(num, 2)).toFixed(4);//转为MB  eg:"3.1725"
  let fileName = 'xxxx.' + fileType;//无法获取图片本来的名字, 只能自定义名字
  this.fetchBase64Data(image.webPath);//获取base64 根据blob地址
}

//异步,返回blob流
async createBlobFromUri(uri: string): Promise<Blob> {
  const response = await fetch(uri);
  const blob = await response.blob();
  return blob;
}

//通过网络请求 获取blob流
fetchBase64Data(fileUrl: string): Promise<string> {
  return new Promise<string>((resolve, reject) => {
    this.http.get(fileUrl, { responseType: 'blob' }).subscribe(
      (blob: Blob) => {
        this.blobToBase64(blob);
      },
      (error) => {
        reject(error);
      }
    );
  });
}

//根据blob流获取 base64string  注意这里用的是 Image类型,
//因为File类型在手机怎么试都不好用,所以转的Image类型 pdf之类的没试过,但估计是不能用
blobToBase64(blob: Blob): Promise<string> {
  return new Promise<string>((resolve, reject) => {
    const image = new Image();
    image.onload = () => {
      const canvas = document.createElement('canvas');
      canvas.width = image.width;
      canvas.height = image.height;
      const context = canvas.getContext('2d');
      context.drawImage(image, 0, 0);
      const base64Data = canvas.toDataURL('image/png');
      this.base64string = base64Data.split(',')[1];
      resolve(base64Data);
    };
    image.onerror = (error) => {
      reject(error);
    };
    const objectUrl = URL.createObjectURL(blob);
    image.src = objectUrl;
  });
}


//这是 File类型的版本,在浏览器好用,手机不清楚哪里写的不对,不好用
fetchBase64Data(fileUrl: string): Promise<string> {
  return new Promise<string>((resolve, reject) => {
    this.http.get(fileUrl, { responseType: 'blob' }).subscribe(
      (blob: Blob) => {

        //判断浏览器是否支持FileReader
if (typeof FileReader == 'undefined') {
  console.log('您的浏览器不支持FileReader');
} else {
  console.log('您的浏览器支持FileReader');
}
        const reader = new FileReader();//定义FileReader类型
        reader.onloadend = () => {
          console.log('run onloadend');
          const base64Data = reader.result as string;
          // 在这里处理 Base64 数据
          this.base64string =base64Data;
          console.log(base64Data);
          resolve(base64Data);
        };//绑定onladend事件的函数
        reader.readAsDataURL(blob);//执行方法
      },
      (error) => {
        reject(error);
      }
    );
  });
}


//前台代码  使用sanitizer.bypassSecurityTrustResourceUrl 方法可以将blob:字符过滤调
<ion-col *ngIf="selectedFileUri">
<img [src]="this.sanitizer.bypassSecurityTrustResourceUrl(selectedFileUri)" alt="Selected Image">
</ion-col>

后续补充,遇到一个问题。在安卓13系统 三星手机上, 发现 修改图片权限始终拿不到,最终将allowEdit属性设为false。不获取该权限解决。 

获取blob地址,页面使用blob地址显示无问题,通过地址获取base64发现无法获取,(未知原因,)最终改为直接获取图片base64.页面显示用base64显示。

<img [src]="base64string">

  async selectFile() {
    let image;
    try {
      image = await Camera.getPhoto({
        quality: 90,
        resultType: CameraResultType.Base64,
        allowEditing: false
      });
    }catch (error){
      console.log('error:'+error);
//当用户取消选择, 或者传入文件损坏时,catch住报错信息,
//是否可以根据报错信息做处理,没有尝试,因为不确定是否所有机型的文言都一致。
    }

    //get file size
    const fileSizeInBytes = image.base64String.length;
    const num = 1024.00;
    const imgSize = (fileSizeInBytes / Math.pow(num, 2)).toFixed(4);

    //get file type
    this.fileType = image.format;

    //get file name
    this.fileName = this.disobj.fileName1 + this.fileType;

    //get file base64
    this.upBase64string=image.base64String;//不带base前缀的 base64string 因为有些服务器的安全策略会拦截base64流,阻止其当作参数传输。
//如无必要,日志中不要出现流文件,很容易将服务器内存占满。
    const imageStr = 'data:image/';
    const baseStr = ';base64,';
    this.base64string = imageStr + this.fileType + baseStr + image.base64String;

    return;
  }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值