Phonegap - 通过路径从相册检索照片

20
在我的PhoneGap / jQuery Mobile应用程序中,我目前正在使用PhoneGap的相机API允许用户拍照,并将其存储在相机胶卷中。我将DestinationType设置为FILE_URI并将此路径保存在本地数据库中。但是,FILE_URI是指向临时位置的路径,当应用程序关闭时会被销毁。我想保存图像的名称,然后从相机胶卷中检索图像。是否有一条路径可以用来以后检索相机胶卷中的图像?
我曾经将图像保存为Base64格式在数据库中,但由于PhoneGap API文档中的这个提示,我对此方法有些担忧:
注意:在较新的设备上使用相机拍摄的图片质量相当好。在某些设备(iPhone 4、BlackBerry Torch 9800)上,使用Base64编码这些图像会导致内存问题。因此,强烈建议使用FILE_URI作为“Camera.destinationType”。
编辑:
通过@Simon MacDonald的答案,我已经让它工作了。这是我的简化代码:
function capturePhoto() {
    navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 25, destinationType: Camera.DestinationType.FILE_URI });
}

function onPhotoURISuccess(imageURI) {
    createFileEntry(imageURI);
}

function createFileEntry(imageURI) {
    window.resolveLocalFileSystemURI(imageURI, copyPhoto, fail);    
}

function copyPhoto(fileEntry) {
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys) { 
        fileSys.root.getDirectory("photos", {create: true, exclusive: false}, function(dir) { 
                fileEntry.copyTo(dir, "file.jpg", onCopySuccess, fail); 
            }, fail); 
    }, fail); 
}

function onCopySuccess(entry) {
    console.log(entry.fullPath)
}

function fail(error) {
    console.log(error.code);
}

我正在尝试处理完全相同的情况,您发布的代码似乎有效,并且我成功地到达了您的onCopySuccess函数,但是我仍然在我的相机胶卷或任何其他相册中看不到图像。在onCopySuccess函数中获得的条目描述了一个在清除temp时被清除的文件。- Yoh Suzuki 刚刚编辑 - Yoh Suzuki
1
以上代码不会将照片保存到相册,而是保存到您的应用程序的“文档”文件夹中。照片的路径看起来像这样:"/var/mobile/Applications/017323CA-35C1-4D50-9CBA-DCC7C697FAF1/Documents/photos/file.jpg"。任意字符串是iOS为您的应用程序创建的文件夹。要将照片保存到相机胶卷中,在getPicture调用中,将此添加到选项对象中:"savePhotoToAlbum":"true"。请注意,您无法获取相机胶卷中图像的路径(据我所知),这就是为什么您必须将其复制保存到您的应用程序的“文档”文件夹中的原因。 - Casey
savePhotoToAlbum 对我来说似乎不起作用,并且在文档中也找不到。 - Yoh Suzuki
啊,我明白了。它实际上是“saveToPhotoAlbum”。而且那个有效! - Yoh Suzuki
抱歉打错了。感谢您修复了它。不确定为什么没在文档中找到它,我忘记了我在哪里找到它,但他们认为它没有出现在文档中是因为它是iOS特定的; 这似乎不是一个好理由。 - Casey
4个回答

10

使用FILE_URI方法检索文件后,您应该使用File API将图像从临时文件夹复制到文档文件夹,并将新路径存储在您的数据库中。

因此,您需要获取getPicture()的结果并将其传递给window.resolveLocalFileSystemURI()以获取FileEntry。然后,您可以调用FileEntry.copyTo()方法备份文件。


1
谢谢。目前为止,一切都很好。我在创建目录以将照片复制到其中时遇到了麻烦,因为我不确定在创建DirectoryEntry实例时应指定什么fullPath参数。文档示例从HTML文档的父级获取了父级,但我并没有成功。您知道fullPath参数应指定什么吗? - Casey
没事了,我自己解决了。谢谢。我马上会在这里发布代码。 - Casey
Simon,我不确定你是否已经有一些实现这个的示例代码了吗? - pleshy

1

0

分享一下我的版本,它使用了 Promises 和 resolveLocalFileSystemURL(不使用 resolveLocalFileSystemURI,因为后者已被弃用)。同时,它还在新创建的文件中使用了原始文件名。

function copyPhotoToAppDir(imageURI) {
  if(!imageURI){
    console.warn("You need to pass imageURI");
    return;
  }

  var fileNameSplit = imageURI.split("/"),
    fileName = fileNameSplit[fileNameSplit.length - 1],
    deferred = $q.defer();

  var copyPhoto = function(fileEntry) {
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys) {
      fileSys.root.getDirectory("photos", {create: true, exclusive: false}, function(dir) {
        fileEntry.copyTo(dir, fileName, onCopySuccess, onFileFail);
      }, onFileFail);
    }, onFileFail);
  };

  var onCopySuccess = function onCopySuccess(entry) {
    console.log("NEW PATH", entry.fullPath);
    deferred.resolve(entry.fullPath);
  };

  var onFileFail = function (error) {
    console.log("COPY FAIL", error);
    deferred.reject();
  };

  window.resolveLocalFileSystemURL(imageURI, copyPhoto, onFileFail);

  return deferred.promise;
}

使用方法:

var uri = "path1";
copyPhotoToAppDir(uri).then(function(newURI){
  console.log(newURI);
});

多个URI的使用:

var uriArr = ["path1", "path2"]; 
  copyPhotoPromises = [];

uriArr.forEach(function(val){
  copyPhotoPromises.push(copyPhotoToAppDir(val));
});
$q.all(copyPhotoPromises).then(function(values){
  console.log("Array with new paths", values);
});

新文件的URI将保存为“/photos/fileName.jpg”。 要获取绝对路径,您可以使用:
cordova.file.documentsDirectory + newFileUri.substring(1);

我在这里使用Angular的$q来处理承诺,但很容易改为jQuery。
deferred = $q.defer();

需要更改为:

deferred = jQuery.Deferred();

干杯


0

很抱歉我不得不创建一个单独的帖子,因为我没有足够的声望来评论。

感谢Simon的建议和Casey的解决方案。

我正在开发一个需要在iOS上拍照、将其保存在目录中并在本地存储中访问链接的Cordova应用程序。用户提交图片后,应用程序需要从目录中删除它。

以下是如何执行此操作以及如何查看项目文档文件夹的附加代码。

您可以使用 $('#pictureid').attr('src')获取要删除的图片的完整目录。

function deletePic(file){
    console.log("deleting: "+file+"...");
    var file = "photos/"+file.toString().split('/').slice(-1)[0]; //gets photo name

    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys){
    fileSys.root.getFile(file, 
                {create:false}, 
                function(entry){
                    entry.remove();
                }, resOnErrorDelete);
                },
    resOnErrorDelete);          
}

function resOnErrorDelete(error) {
    console.log("resOnErrorDelete: "+error.code);
}

如果您有一个带有多个照片附件的表单,您可能想要为存储照片创建的“文档”文件夹赋予一个唯一的名称。这样,您可以在提交批量照片后删除整个文件夹,而不是逐个删除它们。

function deleteFolder(folder){  
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSys){
    fileSys.root.getDirectory(folder, 
                {create:true, exclusive: false}, 
                function(entry){
                    entry.removeRecursively();
                }, resOnErrorDelete);
                },
    resOnErrorDelete);          
}

function resOnErrorDelete(error) {
    console.log("resOnErrorDelete: "+error.code);
}

若要访问项目文件夹,您需要编辑 plist 以启用 iTunes 文件共享

前往[project_folder]/platforms/ios/[project_name]/[project_name]-Info.plist。 右键单击并使用 XCode 打开。

您将看到一个键的表格。在表格下方的任何位置右键单击添加行。将创建一行新记录。双击该键并输入UIFileSharingEnabled。它将自动更改为应用程序支持 iTunes 文件共享,将该键值设为YES

现在,如果您进入 iTunes 并滚动到 iOS 设备的应用程序下方,您会看到“文件共享”区域,其中可以查看您的文件夹。但是,这只适用于“保存到”,无法进行编辑。

希望所有这些附加信息都有所帮助。我花了两天时间进行研究。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接