黑莓10、相机和FILE_NOT_FOUND_ERR

3
我正在尝试在新的黑莓10设备(Z10)中运行一个PhoneGap应用程序,但遇到了问题。基本上,我拍照后想使用FileTransfer将其上传到我的服务器,但是FileTransfer失败并显示FileTransferError.FILE_NOT_FOUND_ERR。
然后,我尝试使用window.resolveLocalFileSystemURI方法,现在出现了FileError.NOT_FOUND_ERR。我假设这两个错误是相关的。
我传递给它们的fileURI是我从navigator.camera.getPicture成功回调中获取的fileURI,看起来像这样:
file:///accounts/1000/shared/camera/IMG_00000037.jpg

我已经使用PhoneGap 2.5.0下载下来的示例黑莓应用,并稍微修改了index.html以复制出现的问题,如下所示:

<!DOCTYPE html>
<!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
-->
<html>
    <head>      
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <title>Hello World</title>

        <script type="text/javascript" charset="utf-8">

        // Called when a photo is successfully retrieved
        //
        function onPhotoURISuccess(imageURI, testFunction) {
            // Uncomment to view the image file URI 
            console.log(imageURI);

            // Get image handle
            //
            var image = document.getElementById('image');

            // Unhide image elements
            //
            image.style.display = 'block';

            // Show the captured photo
            // The inline CSS rules are used to resize the image
            //
            image.src = imageURI;

            // Run our test function
            testFunction(imageURI);
        }

        // Called if something bad happens.
        // 
        function onPhotoURIFail(message) {
            alert('Failed because: ' + message);
        }

        // A button will call this function
        //
        function getPhoto(source, testFunction) {
            // un-sandbox file system to access shared folder
            blackberry.io.sandbox = false;

            // Retrieve image file location from specified source
            navigator.camera.getPicture(
                function(imageURI) {
                    onPhotoURISuccess(imageURI, testFunction);
                },
                onPhotoURIFail,
                {
                    quality: 50,
                    destinationType: Camera.DestinationType.FILE_URI,
                    sourceType: source,
                    correctOrientation: true,
                    saveToPhotoAlbum: true
                }
            );
        }

        // Tests whether we can resolve the imageURI returned from navigator.camera.getPicture
        //
        function testResolveLocalFileSystemURI(imageURI) {
            window.resolveLocalFileSystemURI(
                imageURI,
                function (fileEntry) {
                    var message = "Resolved local file system URI: " + imageURI;
                    document.getElementById("span").innerHTML = message;
                    console.debug(message);
                    console.debug(fileInfo);
                },
                function (error) {
                    var message = "Unable to resolve local file system URI: " + imageURI + " error: " + error.code;
                    document.getElementById("span").innerHTML = message;
                    console.error(message);
                    console.debug(error);
                    console.debug("resolve error source " + error.source);
                    console.debug("resolve error target " + error.target);
                }
            );
        }

        // Tests whether we can upload the imageURI returned from navigator.camera.getPicture using a FileTransfer
        //
        function testFileTransferUpload(imageURI) {

            // Create =the file upload options
            var options = new FileUploadOptions();
            options.fileKey="file";
            options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
            options.mimeType="image/jpeg";

            // Create the file transfer and upload
            var ft = new FileTransfer();
            ft.upload(
                imageURI,
                encodeURI("http://some.server.com/upload.php"),
                function (r) {
                    var message = "Code: '" + r.responseCode + "'' Response: '" + r.response + "'' Sent: '" + r.bytesSent + "'";
                    document.getElementById("span").innerHTML = message;
                    console.debug(message);
                },
                function (error) {
                    var message = "Unable to upload: " + imageURI + " error: " + error.code;
                    document.getElementById("span").innerHTML = message;
                    console.error(message);
                    console.debug(error);
                    console.debug("upload error source " + error.source);
                    console.debug("upload error target " + error.target);
                },
                options
            );
        }

        // Tests whether we can upload the imageURI returned from navigator.camera.getPicture using a FileTransfer
        //
        function testFileSystemGetFile(imageURI) {
            window.requestFileSystem(
                LocalFileSystem.PERSISTENT,
                0,
                function (fileSystem) {
                    fileSystem.root.getFile(
                        imageURI,
                        {create: false},
                        function (fileEntry) {
                            var message = "Got file: " + imageURI;
                            document.getElementById("span").innerHTML = message;
                            console.debug(message);
                            console.debug(fileInfo);
                        },
                        function (error) {
                            var message = "Unable to get file: " + imageURI + " error: " + error.code;
                            document.getElementById("span").innerHTML = message;
                            console.error(message);
                            console.debug(error);
                            console.debug("get file error source " + error.source);
                            console.debug("get file error target " + error.target);
                        }
                    );
                },
                function (error) {
                    var message = "Unable to get file system. error: " + error.code;
                    document.getElementById("span").innerHTML = message;
                    console.error(message);
                    console.debug(error);
                    console.debug("file system error source " + error.source);
                    console.debug("file system error target " + error.target);
                }
            );
        }
        </script>

    </head>
    <body>
        <script type="text/javascript" src="cordova-2.5.0.js"></script>
        <button onclick="getPhoto(Camera.PictureSourceType.CAMERA, testResolveLocalFileSystemURI);">Capture Photo, Test Resolve Local File System URI</button> <br>
        <button onclick="getPhoto(Camera.PictureSourceType.CAMERA, testFileTransferUpload);">Capture Photo, Test File Transfer Upload</button> <br>
        <button onclick="getPhoto(Camera.PictureSourceType.CAMERA, testFileSystemGetFile);">Capture Photo, Test File System Get File</button> <br>
        <img style="display:none;" id="image" width="100" height="100" src="" />
        <span id="span"></span>
    </body>
</html>

每当我运行应用并尝试拍照时,都会出现以下提示信息:
Unable to resolve local file system URI...

为什么FileTransfer或window.resolveLocalFileSystemURI无法找到从navigator.camera.getPicture返回的文件?我有来自phonegap示例的标准config.xml,其中包含所有必需的功能和权限(至少据我所知)。
以下是我的config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
-->
<!--
  Widget Configuration Reference:
    http://docs.blackberry.com/en/developers/deliverables/15274/
-->

<widget xmlns="http://www.w3.org/ns/widgets"
        xmlns:rim="http://www.blackberry.com/ns/widgets"
    version="1.0.0.0" id="org.apache.cordova.example">

  <name>cordovaExample</name>

  <author>Your Name Here</author>

  <description>
       A sample Apache Cordova application that responds to the deviceready event.
  </description>

  <license href="http://opensource.org/licenses/alphabetical">
  </license>

  <!-- Cordova API -->
  <feature id="blackberry.system" required="true" version="1.0.0.0" />
  <feature id="org.apache.cordova" required="true" version="1.0.0" />
  <feature id="blackberry.find" required="true" version="1.0.0.0" />
  <feature id="blackberry.identity" required="true" version="1.0.0.0" />
  <feature id="blackberry.identity.phone" required="true" version="1.0.0.0" />
  <feature id="blackberry.pim.Address" required="true" version="1.0.0.0" />
  <feature id="blackberry.pim.Contact" required="true" version="1.0.0.0" />
  <feature id="blackberry.io.file" required="true" version="1.0.0.0" />
  <feature id="blackberry.utils" required="true" version="1.0.0.0" />
  <feature id="blackberry.io.dir" required="true" version="1.0.0.0" />
  <feature id="blackberry.app" required="true" version="1.0.0.0" />
  <feature id="blackberry.app.event" required="true" version="1.0.0.0" />
  <feature id="blackberry.system.event" required="true" version="1.0.0.0"/>
  <feature id="blackberry.widgetcache" required="true" version="1.0.0.0"/>
  <feature id="blackberry.media.camera" />
  <feature id="blackberry.ui.dialog" />
  <feature id="blackberry.connection" />
  <feature id="blackberry.bbm.platform" />
  <feature id="blackberry.invoke.card" />
  <feature id="blackberry.pim.contacts" />
  <feature id="blackberry.ui.contextmenu" />
  <feature id="blackberry.io.filetransfer" />
  <feature id="blackberry.io" />
  <feature id="blackberry.invoke" />
  <feature id="blackberry.invoked" />
  <feature id="blackberry.push" />
  <feature id="blackberry.media.microphone" required="true" version="1.0.0.0"/>

  <!-- Cordova API -->
  <access subdomains="true" uri="file:///store/home" />
  <access subdomains="true" uri="file:///SDCard" />
  <access subdomains="true" uri="file:///accounts" />

  <!-- Expose access to all URIs, including the file and http protocols -->
  <access subdomains="true" uri="*" />

  <icon rim:hover="false" src="res/icon/blackberry/icon-80.png" />
  <icon rim:hover="true" src="res/icon/blackberry/icon-80.png" />

  <rim:loadingScreen backgroundColor="#CFCFCF"
                     foregroundImage="res/screen/blackberry/screen-225.png"
             onFirstLaunch="true">
    <rim:transitionEffect type="fadeOut" />
  </rim:loadingScreen>

  <content src="index.html" />

  <rim:permissions>
    <rim:permit>use_camera</rim:permit>
    <rim:permit>read_device_identifying_information</rim:permit>
    <rim:permit>access_shared</rim:permit>
    <rim:permit>read_geolocation</rim:permit>
    <rim:permit>record_audio</rim:permit> 
    <rim:permit>access_pimdomain_contacts</rim:permit> 
  </rim:permissions>

</widget>

以下是我的plugins.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
-->
<plugins>
  <plugin name="App"            value="org.apache.cordova.app.App"/>
  <plugin name="Device"         value="org.apache.cordova.device.Device"/>
  <plugin name="Camera"         value="org.apache.cordova.camera.Camera"/>
  <plugin name="NetworkStatus"  value="org.apache.cordova.network.Network"/>
  <plugin name="Notification"   value="org.apache.cordova.notification.Notification"/>
  <plugin name="Accelerometer"  value="org.apache.cordova.accelerometer.Accelerometer"/>
  <plugin name="Geolocation"    value="org.apache.cordova.geolocation.Geolocation"/>
  <plugin name="File"           value="org.apache.cordova.file.FileManager"/>
  <plugin name="FileTransfer"   value="org.apache.cordova.http.FileTransfer"/>
  <plugin name="Contacts"       value="org.apache.cordova.pim.Contact"/>
  <plugin name="Capture"        value="org.apache.cordova.capture.MediaCapture"/>
  <plugin name="Battery"        value="org.apache.cordova.battery.Battery"/>
  <plugin name="Media"          value="org.apache.cordova.media.Media"/>
  <plugin name="Globalization"  value="org.apache.cordova.globalization.Globalization"/>
</plugins>

重现问题的步骤:

  1. 按照此指南进行操作(使用 BlackBerry 10(QNX) 步骤)
  2. 用我提供的 index.html 文件替换给定的文件
  3. 用我提供的 config.xml 文件替换给定的文件(更改应该最小化)
  4. 在 BB10 设备上进行调试(我正在使用 Z10)
  5. 单击“捕获照片”按钮,如果您连接了远程 Web 检查器,则应该会看到错误信息。

我也在PhoneGap google group上发布了这个。 - niltz
除了在黑莓开发者论坛上得到一些反馈外,我已经根据建议更新了上面的示例,但仍然没有成功。 - niltz
6个回答

2

你需要执行 blackberry.io.sandbox = false; 并且去掉 file:// 协议,至少根据我的经验从文件系统访问文件需要这样做。此外,你不应该直接访问共享路径。请使用 blackberry.io.sharedFolder 属性,如本页面示例所示:https://developer.blackberry.com/html5/apis/blackberry.io.html

你的文件系统路径应该是 blackberry.io.sharedFolder + 'camera/IMG_00000037.jpg'

BB10 的安全沙盒设计意味着每个应用程序都有自己的文件路径来访问共享文件系统区域。


这对我有用。关键是那个奇怪的文件系统路径,不要使用resolveLocalFileSystemURI,因为URI不是本地的,它是“共享”的。希望Phonegap的开发人员能够修复这个问题,使camera.getPicture返回正确格式的URL。 - Mister Smith

1

1
这只是将错误更改为代码5(ENCODING_ERR),意味着URI无效。 - Mister Smith

0

我最近几天也遇到了同样的问题。获取图片突然停止工作,而我的代码没有任何更改。

要注意 cordova-plugin-file 插件,因为在它的 3.0.1-dev 版本(可能还有其他版本),你开发的应用程序不会请求访问文件的权限,从相机或图库获取图片将失败。

我使用了这个插件的 2.1.0 版本来解决这个问题:

cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-file.git#r2.1.0

0

相信我,这个问题可以通过这个源代码解决:

<html>
<head>
<script type="text/javascript" src="local:///chrome/webworks.js"></script>
<script type="text/javascript">

function log(e) {
    console.log(e);
}

function takePicture(success) {
    blackberry.invoke.card.invokeCamera('photo', function (path) {
        success(path);
    }, log, log);
}

function openFile (filePath, success) {
    window.webkitRequestFileSystem(window.PERSISTENT, 1024*1024*1024, function (fs) {
        fs.root.getFile(filePath, {}, function (entry) {
            success(entry);
        }, log);
    }, log);
}

function uploadFile (entry, server, success) {
    entry.file(function (file) {
        var fd = new FormData(),
            xhr;
        fd.append("picture", file);
        xhr = new XMLHttpRequest();
        xhr.open("POST", server);
        xhr.onload = function (evt) {
            if (xhr.status == 200) {
                success(xhr.response);
            } else {
                log(xhr);
            }
        };
        xhr.ontimeout = log;
        xhr.onerror = log;
        xhr.send(fd);
    }, log);
}

function start() {
    takePicture(function (filePath) {
        openFile(filePath, function (entry) {
            uploadFile(entry, "http://cordova-filetransfer.jitsu.com/upload", function () {
                alert("SUCCESS");
            });
        });
    });
}

document.addEventListener('webworksready', function () {
    blackberry.io.sandbox = false;
    document.getElementById("startButton").disabled = "";
});

</script>
</head>
<body>
<h1>Camera XHR Upload Sample</h1>
<button id="startButton" disabled="disabled"  onclick="start();">Start</button>
</body>
</html>

0

基于chadtatro在2013年4月2日的回答:

请在config.xml中添加

<access uri="file:///accounts/1000/removable/sdcard/" subdomains="true"/>

我也添加了到我的项目中:

webworks plugin add com.blackberry.io

0

你可能想尝试使用 <access uri="file://accounts/" subdomains="ture"/> 代替 'store/home'。

另外,当处理文件系统时,你需要将沙盒模式设置为 false,否则可能无法访问该文件。

blackberry.io.sandbox = false;

除此之外,看起来你已经几乎把所有东西都设置好了。


1
我尝试了你的建议,但仍然不行。我已经更新了原始帖子并更新了config.xml和index.html。请注意,在file:///中缺少一个斜杠并且true拼写错误。当我添加它们时,我确保这些都是正确的。 - niltz

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