Cordova-在<img/>标签中显示本地图像文件

时间:2018-12-13 13:49:06

标签: ios cordova ember.js

我有一个Cordova应用程序(基于Ember.js构建,使用Corber插件),我目前仅在iOS上运行,特别是iOS模拟器(iPhone 8,iOS v12),因此它使用的是{{1} }。

该应用程序正在使用cordova的文件插件下载远程图像并将其存储在用户设备上,该设备当前位于“文档”(WKWEBVIEW)中,效果很好,并且我已经验证了这些图像是否可以在事实在那里。但是,我无法通过标准cordova.file.documentsDirectory标签找出用于在应用中显示这些图像的正确URL / URI。

Cordova自己的文档说使用<img>协议路径(https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/#cdvfile-protocol),但是即使按照那里的说明进行操作(向index.html添加content-security元标记,访问规则也要config.xml等),似乎WKWEBVIEW完全不支持此协议,当我尝试使用它时,在控制台中出现“不受支持的URL”错误。

关于该主题的其他SO答案建议使用相对于cordova应用程序的Web服务器URL的常规URL路径,例如cdvfile://之类的东西,但我尝试使用404的任何路径。

这似乎是一个简单/常见的用例,但是我很沮丧。

2 个答案:

答案 0 :(得分:1)

对于像我一样挣扎的其他人-还有一个解决方案,它不需要对我在绝望的日子里找不到解决方案后发现的代码进行重大更改

需要2个步骤:

首先使用以下命令更新您的config.xml

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns # improves plot aesthetics
import copy

fig = plt.figure(figsize=(3, 3),dpi=1200)


variables = ("Average ","D", "C",  
            "Eenergy", "Energy2", "Preference")

data = (3.8,0, 17,  
        1200, 400, 10)
ranges = [(1, 5), (60,0), (200, 0), 
         (700, 1500), (1000, 200), (0, 10)]   

n_ordinate_levels=5

angles = np.arange(0, 360, 360./len(variables))

axes = [fig.add_axes([0.1,0.1,0.9,0.9],polar=True,
                label = "axes{}".format(i)) 
                for i in range(len(variables))]
l, text = axes[0].set_thetagrids(angles,labels=variables,fontsize=10)

axes[0].set_thetagrids(angles,labels=variables,fontsize=10,rotation=90)
   
for txt, angle in zip(text, angles):
            txt.set_rotation(angle-90)
            
for ax in axes[1:]:
    ax.patch.set_visible(False)
    ax.grid("off")
    ax.xaxis.set_visible(False)

for ax in axes[1:]:
            ax.patch.set_visible(False)
            ax.grid("off")
            ax.xaxis.set_visible(False)

for i, ax in enumerate(axes):
    grid = np.linspace(*ranges[i],num=n_ordinate_levels)

    if ranges[i][0] > ranges[i][1]:
        grid = copy.deepcopy(grid[::-1]) # hack to invert grid
                          # gridlabels aren't reversed
        gridlabel = ["{:d}".format(int(x)) 
                         for x in grid]    
        gridlabel[n_ordinate_levels-1] = "" # clean up origin
            
    else:
        gridlabel = ["{:d}".format(int(x)) 
                     for x in grid]
        gridlabel[0] = "" # clean up origin
            
    print(grid)
    ax.set_rgrids(grid, labels=gridlabel,angle=angles[i],fontsize=8,fmt='%i',c='black')
    ax.xaxis.set_zorder(0)
    ax.spines['polar'].set_visible(False)
    ax.set_ylim(*ranges[i])
            
    
plt.rc('grid', color='grey', linewidth=1, linestyle='-')
fig.show()
fig.savefig(fname="test.pdf",bbox_inches="tight")

然后使用未公开的方法转换file://链接

<platform name="ios">    
  <preference name="scheme" value="app" />
  <preference name="hostname" value="localhost" />
 </platform>

此方法执行到虚拟本地链接的转换,该链接使文件可访问并绕过WkWebView限制。这样的样本会更长一些

window.WkWebView.convertFilePath(filePath)

答案 1 :(得分:0)

我没有使用Cordova,但是您链接的文档说的是:

  

要将cdvfile用作标记的src,您可以通过已解析的fileEntry的toURL()方法将其转换为本地路径,可以通过resolveLocalFileSystemURL获得它-参见以下示例。

并举例说明:

resolveLocalFileSystemURL('cdvfile://localhost/temporary/path/to/file.mp4', function(entry) {
    var nativePath = entry.toURL();
    console.log('Native URI: ' + nativePath);
    document.getElementById('video').src = nativePath;

鉴于所有这些,我想说您可以尝试创建一个组件cdv-img。我认为像这样的东西应该起作用:

import Component from '@ember/component';

export default Component.extend({
  tagName: 'img',
  cdvPath: undefined,
  didReceiveAttrs() {
    this._super(...arguments);
    if (this.cdvPath) {
      resolveLocalFileSystemURL(this.cdvPath, (entry) => {
        this.$().attr('src', entry.toURL());
      });
    }
  },
});

像这样使用它:

{{cdv-img cdvPath='cdvfile://localhost/temporary/path/to/file.jpg'}}

UPD

如果它不适用于文件协议,则可以尝试将图像转换为数据url

import Component from '@ember/component';

export default Component.extend({
  tagName: 'img',
  cdvPath: undefined,
  didReceiveAttrs() {
    this._super(...arguments);
    if (this.cdvPath) {
      const el = this.$();
      resolveLocalFileSystemURL(this.cdvPath, (entry) => {
        entry.file(function (file) {
          const reader = new FileReader();

          reader.onloadend = function() {
            el.attr('src', this.result);
          };

          reader.readAsDataURL(file);
        });
      });
    }
  },
});