Electron에서 로컬 이미지 파일 보기
17381 단어 Electron
개요
Electron의 응용 프로그램을 개발하는 동안 내장 이미지를 보려고 할 때 "Not allowed to load local resource"라는 오류가 발생했으므로 그 조치를 기록해 둡니다.
패키지화하면 대책을 치지 않아도 이미지가 표시될 수 있습니다.
검증하면 나중에 추기한다고 생각합니다.
결론부터 말하면, file 프로토콜을 그만두고, <img src="data:image/png;base64,<画像をbase64化した文字列>"/>
를 사용해 해결했습니다.
상대 경로에서의 지정 문제(다른 문제가 발생하기 때문에, 후술하는 대책을 실시)
Electron 앱은 React를 사용하고 create-react-app로 만든 앱으로 Electron화한 것입니다.
index.html 옆에 logo.png를 넣고 태그에서 <img src="../build/logo.png"/>
로 표시하려고했습니다.
이미지는 웹 앱으로 표시되지만 Electron에서는 src="file:///build/logo.png"
가 되어 절대 경로로 검색하게 됩니다.
이 대책으로서, 이하의 사이트를 참고로, protocol.interceptFileProtocol
라고 하는 API로, "file:///%RELATIVE_PATH%"(RELATIVE_PATH는 매직워드)로 시작되고 있으면, 상대 패스로서 핸들 하도록 구현했습니다.
Electron 앱은 React를 사용하고 create-react-app로 만든 앱으로 Electron화한 것입니다.
index.html 옆에 logo.png를 넣고 태그에서
<img src="../build/logo.png"/>
로 표시하려고했습니다.이미지는 웹 앱으로 표시되지만 Electron에서는
src="file:///build/logo.png"
가 되어 절대 경로로 검색하게 됩니다.이 대책으로서, 이하의 사이트를 참고로,
protocol.interceptFileProtocol
라고 하는 API로, "file:///%RELATIVE_PATH%"(RELATIVE_PATH는 매직워드)로 시작되고 있으면, 상대 패스로서 핸들 하도록 구현했습니다.Electron에서 절대 경로의 기준점을 애플리케이션이 있는 디렉토리로 설정
htps : // 이 m / 츠치 에에 / 있어 ms / 4123784 f1 에 b68 아 1d3925
img 태그의 지정은,
<img src="%RELATIVE_PATH%../build/logo.png" />
라고 해, 소스는 이런 느낌입니다.protocol.interceptFileProtocol('file', (req, callback) => {
const requestedUrl = req.url.substr(7);
if (path.startsWith("/%RELATIVE_PATh%") {
callback(path.normalize(path.join(__dirname, requestedUrl.substring("/%RELATIVE_PATh%".length)));
} else {
callback(requestedUrl);
}
이 대책은 Mac에서는 작동했지만 Windows에서는 "Not allowed to load local resource"라는 오류가 발생하여 작동하지 않았습니다.
Not allowed to load local resource 대책(해결됨)
Google에서 몇 가지 조사했지만, Websecurity를 Off로 하는, create-react-app를 eject(비가역의 조작으로, create-react-app의 장점이 없어진다)하거나, webpack의 컨피그를 바꾸는 등이라고 하는 것 그래서 적용해도 효과가 없었습니다.
htps : // 기주 b. 코 m / 에 ct 론 / 에 ct 론 / 이스에 s / 5107 # 이스에 코멘 t-299971806
htps : // 기주 b. 코 m / 에ct 론 / 에 ct 론 / 이스에 s / 5107
결국은, 아래에 인용한 h tps : // s t c ゔ ぇ rf ぉ w. 코 m / 쿠에 s 치온 s / 50272451 / 에ぇct 론 - js - 펑크 s - f 로 m ぉ 카 l - ぃ ぇ - sys m 에 쓰여져 있듯이, file 프로토콜을 사용하고 있는 한 시큐리티를 Off로 하는 등의 해결책 밖에 없고, 문제는 해결하지 않았습니다.
Electron by default allows local resources to be accessed by render processes only when their html files are loaded from local sources with the file://protocol for security reasons.
If you are loading the html from any http://or https://protocol even from a local server like webpack-dev-server, access to local resources is disabled.
If you loading html pages from a local server only during development and switching to local html files in production, you can disable websecurity during development, taking care to enable it in production.
최종 솔루션
` <img src="data:image/png;base64,<画像をbase64化した文字列>"/>
라는 방식으로 해결했습니다.
해결 후 폴더 구성은 다음과 같습니다.
build/ <= publicとsrcのビルド結果が格納される。
public/index.html
logo.png
src/ ...
libs/ImageLoader.js
main.js <= ElectronのMainプロセスの起動ファイル
해결을 위한 단계는 다음과 같습니다.
1. main.js에서, images 폴더 이하의 png/jpg 파일을 base64화해, global의 변수에 채운다.
2. ImageLoader.js 클래스를 만들고 src에 전달할 문자열을 생성합니다.
3. jsx에서 img 태그에 step2로 생성 된 문자열을 전달합니다.
소스는 다음과 같습니다.
build/ <= publicとsrcのビルド結果が格納される。
public/index.html
logo.png
src/ ...
libs/ImageLoader.js
main.js <= ElectronのMainプロセスの起動ファイル
main.js
const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')
const url = require('url')
const fs = require('fs')
const info = {
win: null,
images: {}
}
global.info = info
let win
function createWindow () {
win = new BrowserWindow({width: 800, height: 600, resizable:true})
info.win = win
// images以下のフォルダを捜査
const files = fs.readdirSync(path.join(__dirname, '/../build/images'))
files.forEach((file)=>{
const ext = path.extname(file)
if(ext === '.png' || ext === '.jpg') {
const binary = fs.readFileSync(path.join(__dirname, '/../build/images/' + file))
// base64化
const base64data = new Buffer(binary).toString('base64')
// マップに詰める
info.images[file] = {
type: ext.substring(1),
name: file,
data: base64data
}
}
})
// 通常のElectronのメイン処理
win.loadURL(url.format({
pathname: path.join(__dirname, '/../build/index.html'),
protocol: 'file:',
slashes: true
}))
// 以下省略・・・
ImageLoader.js
const electron = window.require('electron')
//globalを取得するには、electron.remoteで取得する
const remote = electron.remote
class ImageLoader {
static loadSrc = (imagePath) => {
const info = remote.getGlobal('info')
const image = info.images[imagePath]
for(let key in info.images) {
console.log(key + " " + info.images[key].type + " " + info.images[key].name)
}
if(image === undefined)
return "image not found"
// data:image/<png|jpg>;base64,<base64 encoded data>の生成
return `data:image/${image.type};base64,${image.data}`
}
}
export default ImageLoader
App.jsx
import React from 'react'
import ImageLoader from '../libs/ImageLoader'
/* アプリケーション画面の定義 */
const App = () => (
<div>
<img src={ImageLoader.loadSrc('logo.png')} height="64px" width="64px"/>
// 以下省略・・・
사이고에게
대책의 비망록으로 기재하고 있습니다.
다른 방법도 있을지도 모르기 때문에, 아시면 알려 주시면 다행입니다.
Reference
이 문제에 관하여(Electron에서 로컬 이미지 파일 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tashxii/items/a92abc810b922c187a1b
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Electron에서 로컬 이미지 파일 보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tashxii/items/a92abc810b922c187a1b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)