You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ionic7+Capacitor5+Vue3相机拍照上传PDF报错求助

Ionic7 + Capacitor5 + Vue3:相机拍照生成PDF上传后端报错"Path cannot be empty"

问题背景

开发发票列表与PDF上传应用,包含三个功能:

  • 从存储选择PDF并上传
  • 从相册选图合并为PDF上传(正常运行)
  • 相机拍照合并为PDF上传(出现异常)

使用相机拍照后点击上传,Symfony后端返回错误:

{
"class": "RuntimeException",
"file": "/var/www/html/wms-dev/vendor/guzzlehttp/psr7/src/Utils.php",
"line": 389,
"status_text": "Internal Server Error",
"message": "Unable to open "" using mode "r": Path cannot be empty",
...
}

问题分析

相册选图与相机拍照的核心差异在于图片资源的加载逻辑:

  • 相册选图返回的webPath是本地文件路径,浏览器可直接加载
  • 相机拍照返回的webPath是Capacitor临时URL(如capacitor://localhost/...),直接用img.src加载可能存在跨域或资源无法访问的问题,导致图片加载失败,生成的PDF内容为空,最终上传时后端接收空文件触发报错。

修复方案

修改createPdfFromPhotosAndUpload函数中的图片加载逻辑,通过fetch将webPath转换为Blob后生成可访问的临时URL,确保相机拍摄的图片能被正确加载:

async createPdfFromPhotosAndUpload() {
    this.sendingLoading = true
    try {
        const selectedPhotos = this.photos.filter((photo: any) => photo.selected);
        console.log("length of selectedPhotos Array ===>", selectedPhotos.length)

        if (selectedPhotos.length === 0) {
            console.log('No photos selected');
            return;
        }

        const pdfDocs: Uint8Array[] = [];

        for (const photo of selectedPhotos) {
            const pdf = new jsPDF();
            // 替换原图片加载逻辑,通过fetch获取Blob并生成临时URL
            const response = await fetch(photo.webPath);
            const blob = await response.blob();
            const imgUrl = URL.createObjectURL(blob);
            
            const img = new Image();
            img.src = imgUrl;

            await new Promise<void>((resolve, reject) => {
                img.onload = () => {
                    URL.revokeObjectURL(imgUrl); // 释放临时URL内存
                    const imgWidth = 180;
                    const imgHeight = (img.height * imgWidth) / img.width;
                    pdf.addImage(img, 'JPEG', 15, 15, imgWidth, imgHeight);

                    const pdfBytes = new Uint8Array(pdf.output('arraybuffer'));
                    pdfDocs.push(pdfBytes);
                    resolve();
                };
                
                // 处理图片加载失败的情况
                img.onerror = (error) => {
                    console.error('Failed to load image:', error);
                    reject(new Error(`Image load failed: ${photo.webPath}`));
                };
            });
        }

        // 合并PDF逻辑保持不变
        const mergedPdf = await PDFDocument.create();
        for (const pdfBytes of pdfDocs) {
            const pdf = await PDFDocument.load(pdfBytes);
            const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
            copiedPages.forEach(page => mergedPdf.addPage(page));
        }

        const mergedPdfBytes = await mergedPdf.save();
        const pdfDocument = new File([mergedPdfBytes], 'mergedDocument.pdf', { type: 'application/pdf' });
        console.log("pdfDocument ===>", pdfDocument)

        const res = await this.uploadDocument(pdfDocument)
        if(res){
            this.photos = this.photos.filter((photo: any) => !photo.selected)
            this.showToast('Document Envoyé !', 2000, 'success', planeIcon)
            if(!this.photos.length) this.togglePhotosModal()
        } 
    } catch (error) {
        console.error("error creating pdf !!", error)
    } finally {
        this.sendingLoading = false
    }
}

额外验证方案

如果上述修复仍无效,可尝试将相机拍照的返回格式改为Base64,直接使用字符串加载图片:

async prendrePhoto(){
    this.isUsingCamera = true
    const photo = await Camera.getPhoto({
        resultType: CameraResultType.Base64, // 修改为Base64格式
        source: CameraSource.Camera,
        quality: 100
    }) 
    const photoWithSelected = {
        ...photo,
        selected: true,
        // 生成Base64格式的图片URL
        imgUrl: `data:image/${photo.format};base64,${photo.base64String}`
    }
    this.photos.push(photoWithSelected)
    if(!this.isPhotosModalOpen) this.togglePhotosModal()
    console.log("Photos taken ===>", this.photos)
}

之后在生成PDF时,将img.src = photo.webPath替换为img.src = photo.imgUrl即可。

内容的提问来源于stack exchange,提问作者Chadizar Royland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 05:23:09