document.getElementById("myFile").value 使用 electron 未定义
document.getElementById("myFile").value gets undefined using electron
我有一个非常基本的 html 文件(使用电子);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> File Uploader </title>
<link rel="stylesheet" href="style.css">
<script defer src="render.js"></script>
</head>
<body>
<h1>Drive File Uploader</h1>
<input type="file" id="myFile" name="myFile">
<button onclick="FileUploadPing()">Upload your file</button>
</body>
</html>
和一个名为 render.js;
的事件侦听器
const ipcRenderer = require("electron").ipcRenderer;
const FileUploadPing = () => {
var input = document.getElementById("myFile").value
if (input) {
ipcRenderer.send("FileUploadPing",inputVal);
}else{console.log("no path value")}
};
ipcRenderer.on("FileRecievePing", (event, data) => {
alert(data)
});
但是当我点击提交时,document.getElementById("myFile").value
returns undefined
如何提取该值?
这是一个有趣的问题,许多使用 Electron 的人都会遇到这个问题。可以使用(通过 Electron)原生的 OS dialog.showOpenDialog([browserWindow, ]options) dialog or the html <input type="file"> 标签。
为了避免管理 is prefixed with C:\fakepath\ 问题的需要,通常最好使用本机方法。毕竟,那是 Electron 最擅长的。
让我向您展示如何快速设置一个 html 按钮,单击该按钮将打开本机文件选择器对话框,并且在选择路径时,return 渲染路径用于显示的线程。
在下面的代码中,我们将使用配置为通信的 preload.js
脚本(using IPC) between the main thread and render thread(s). Context Isolation 将对此进行更详细的描述。
首先,让我们编写 main.js
文件,其中将包含本机文件对话框的创建。
main.js
(主线程)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronDialog = require('electron').dialog;
const electronIpcMain = require('electron').ipcMain;
const nodePath = require("path");
// Prevent garbage collection
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 1000,
height: 700,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('index.html')
.then(() => { window.show(); })
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// Open the file dialog
electronIpcMain.on('message:openDialog', (event) => {
let options = {
title: 'Select File',
properties: ['openFile']
};
electronDialog.showOpenDialog(window, options)
.then((result) => {
if (result.canceled) {
console.log('User cancelled file dialog.');
return;
}
event.reply('message:dialogPath', result.filePaths[0]);
})
.catch((error) => { console.error(error); });
})
现在,让我们创建 index.html
文件,为了简单起见,它还在 <script>
标签中包含 Javascript。
NB: Instead of deferring your script in the <head>
, you can include it just before the closing <html>
tag. Placing it here effectively performs the same thing as defer
in the <head>
<script>
tag.
index.html
(渲染线程)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Drive File Uploader</title>
</head>
<body>
<div>Drive File Uploader</div>
<hr>
<label for="path">Path: </label>
<input type="text" id="path" name="path">
<input type="button" id="open-dialog" name="open-dialog" value="...">
<input type="button" id="upload" value="Upload">
</body>
<script>
// Let's declare it as it is used more than once
let filePath = document.getElementById('path');
// Event listeners
document.getElementById('open-dialog').addEventListener('click', () => { window.ipcRender.send('message:openDialog'); });
document.getElementById('upload').addEventListener('click', () => { console.log(filePath.value); });
// IPC message from the main thread
window.ipcRender.receive('message:dialogPath', (path) => { filePath.value = path; })
</script>
</html>
最后,让我们添加 preload.js
脚本以允许主线程和渲染线程安全地相互通信。
Note: This is where we define our whitelisted channel names.
preload.js
(主线程)
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// White-listed channels.
const ipc = {
'render': {
// From render to main.
'send': [
'message:openDialog'
],
// From main to render.
'receive': [
'message:dialogPath'
],
// From render to main and back again.
'sendReceive': []
}
};
// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods.
'ipcRender', {
// From render to main.
send: (channel, args) => {
let validChannels = ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, listener) => {
let validChannels = ipc.render.receive;
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`.
ipcRenderer.on(channel, (event, ...args) => listener(...args));
}
},
// From render to main and back again.
invoke: (channel, args) => {
let validChannels = ipc.render.sendReceive;
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
}
}
);
希望以上概述了使用(通过 Electron)本机对话框是多么简单。好处是它们具有 OS 特定的功能和感觉。
我不知道我做了什么不同,但是当我尝试这个时它突然起作用了。
main.js;
const { app, BrowserWindow, ipcMain } = require("electron");
let win = null;
const createWindow = () => {
win = new BrowserWindow({
width: 800,
height: 600,
resizable: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
nativeWindowOpen: true,
},
});
win.loadFile("index.html");
};
app.whenReady().then(createWindow);
render.js;
const ipcRenderer = require("electron").ipcRenderer;
const {uploadFileToCloud} = require("C:/Users/efeba/desktop/pythonAndJS/ITGSProject/app.js")
const FileUploadPing = () => {
var name = document.getElementById("myFile").value
name = name.replace("C:\fakepath\","")
console.log(name)
var path = document.getElementById("myFile").files[0].path
path = path.replace(name,"")
path = path.replaceAll("\", "/") // beautify the string
console.log(path)
if (path) {
uploadFileToCloud(name, path)
alert("File Uploaded")
}else{console.log("no path value")}
};
//file uploads but content is empty
//I suspect pulling the libraries in renderer has some problems, will
//try to make it by sending a ping to main.js
index.html;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> File Uploader </title>
<link rel="stylesheet" href="style.css">
<script defer src="render.js"></script>
</head>
<body>
<h1>Drive File Uploader</h1>
<input type="file" id="myFile" name="myFile">
<button onclick="FileUploadPing()">Upload your file</button>
</body>
</html>
希望能帮到你
我有一个非常基本的 html 文件(使用电子);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> File Uploader </title>
<link rel="stylesheet" href="style.css">
<script defer src="render.js"></script>
</head>
<body>
<h1>Drive File Uploader</h1>
<input type="file" id="myFile" name="myFile">
<button onclick="FileUploadPing()">Upload your file</button>
</body>
</html>
和一个名为 render.js;
的事件侦听器const ipcRenderer = require("electron").ipcRenderer;
const FileUploadPing = () => {
var input = document.getElementById("myFile").value
if (input) {
ipcRenderer.send("FileUploadPing",inputVal);
}else{console.log("no path value")}
};
ipcRenderer.on("FileRecievePing", (event, data) => {
alert(data)
});
但是当我点击提交时,document.getElementById("myFile").value
returns undefined
如何提取该值?
这是一个有趣的问题,许多使用 Electron 的人都会遇到这个问题。可以使用(通过 Electron)原生的 OS dialog.showOpenDialog([browserWindow, ]options) dialog or the html <input type="file"> 标签。
为了避免管理 is prefixed with C:\fakepath\ 问题的需要,通常最好使用本机方法。毕竟,那是 Electron 最擅长的。
让我向您展示如何快速设置一个 html 按钮,单击该按钮将打开本机文件选择器对话框,并且在选择路径时,return 渲染路径用于显示的线程。
在下面的代码中,我们将使用配置为通信的 preload.js
脚本(using IPC) between the main thread and render thread(s). Context Isolation 将对此进行更详细的描述。
首先,让我们编写 main.js
文件,其中将包含本机文件对话框的创建。
main.js
(主线程)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronDialog = require('electron').dialog;
const electronIpcMain = require('electron').ipcMain;
const nodePath = require("path");
// Prevent garbage collection
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 1000,
height: 700,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('index.html')
.then(() => { window.show(); })
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// Open the file dialog
electronIpcMain.on('message:openDialog', (event) => {
let options = {
title: 'Select File',
properties: ['openFile']
};
electronDialog.showOpenDialog(window, options)
.then((result) => {
if (result.canceled) {
console.log('User cancelled file dialog.');
return;
}
event.reply('message:dialogPath', result.filePaths[0]);
})
.catch((error) => { console.error(error); });
})
现在,让我们创建 index.html
文件,为了简单起见,它还在 <script>
标签中包含 Javascript。
NB: Instead of deferring your script in the
<head>
, you can include it just before the closing<html>
tag. Placing it here effectively performs the same thing asdefer
in the<head>
<script>
tag.
index.html
(渲染线程)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Drive File Uploader</title>
</head>
<body>
<div>Drive File Uploader</div>
<hr>
<label for="path">Path: </label>
<input type="text" id="path" name="path">
<input type="button" id="open-dialog" name="open-dialog" value="...">
<input type="button" id="upload" value="Upload">
</body>
<script>
// Let's declare it as it is used more than once
let filePath = document.getElementById('path');
// Event listeners
document.getElementById('open-dialog').addEventListener('click', () => { window.ipcRender.send('message:openDialog'); });
document.getElementById('upload').addEventListener('click', () => { console.log(filePath.value); });
// IPC message from the main thread
window.ipcRender.receive('message:dialogPath', (path) => { filePath.value = path; })
</script>
</html>
最后,让我们添加 preload.js
脚本以允许主线程和渲染线程安全地相互通信。
Note: This is where we define our whitelisted channel names.
preload.js
(主线程)
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// White-listed channels.
const ipc = {
'render': {
// From render to main.
'send': [
'message:openDialog'
],
// From main to render.
'receive': [
'message:dialogPath'
],
// From render to main and back again.
'sendReceive': []
}
};
// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods.
'ipcRender', {
// From render to main.
send: (channel, args) => {
let validChannels = ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, listener) => {
let validChannels = ipc.render.receive;
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`.
ipcRenderer.on(channel, (event, ...args) => listener(...args));
}
},
// From render to main and back again.
invoke: (channel, args) => {
let validChannels = ipc.render.sendReceive;
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
}
}
);
希望以上概述了使用(通过 Electron)本机对话框是多么简单。好处是它们具有 OS 特定的功能和感觉。
我不知道我做了什么不同,但是当我尝试这个时它突然起作用了。
main.js;
const { app, BrowserWindow, ipcMain } = require("electron");
let win = null;
const createWindow = () => {
win = new BrowserWindow({
width: 800,
height: 600,
resizable: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
nativeWindowOpen: true,
},
});
win.loadFile("index.html");
};
app.whenReady().then(createWindow);
render.js;
const ipcRenderer = require("electron").ipcRenderer;
const {uploadFileToCloud} = require("C:/Users/efeba/desktop/pythonAndJS/ITGSProject/app.js")
const FileUploadPing = () => {
var name = document.getElementById("myFile").value
name = name.replace("C:\fakepath\","")
console.log(name)
var path = document.getElementById("myFile").files[0].path
path = path.replace(name,"")
path = path.replaceAll("\", "/") // beautify the string
console.log(path)
if (path) {
uploadFileToCloud(name, path)
alert("File Uploaded")
}else{console.log("no path value")}
};
//file uploads but content is empty
//I suspect pulling the libraries in renderer has some problems, will
//try to make it by sending a ping to main.js
index.html;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title> File Uploader </title>
<link rel="stylesheet" href="style.css">
<script defer src="render.js"></script>
</head>
<body>
<h1>Drive File Uploader</h1>
<input type="file" id="myFile" name="myFile">
<button onclick="FileUploadPing()">Upload your file</button>
</body>
</html>
希望能帮到你