文件处理 - 本地文件加载
我们在使用 electron 时, 有时会涉及一些文件的处理, 比如文件的下载, 或者本地文件的加载 (本地音乐, 本地图片等), 本章主要介绍 electron 本地文件的加载.
其实这个功能还是比较常见的, 比如我们下载了某某皮肤主题本地, 想在本地加载, 或者是做一个音乐播放器, 加载本地音乐进行播放.
目标: 使用 input file 获取图片或者音乐文件的本地地址 (当然你可以直接用已有文件的本地地址), 进行展示和播放.
web 本地文件加载
浏览器为了安全考虑, 在 Web 页面进行文件加载时, 是禁用了 file:// 协议进行文件展示的, 一般来说要想获取本地文件展示, 得让用户进行 input file 选择, 获取 File 对象, 对这个 File 对象进行操作展示:
- <a-upload
- :customRequest="customRequest"
- name="file"
- :showUploadList="false"
- :multiple="true"
- >
- <a-button>
- <upload-outlined></upload-outlined>
添加图片
- </a-button>
- </a-upload>
- <a-image
- :width="200"
- :height="200"
- :src="state.image"
- />
- function customRequest(fileData) {
- const file = fileData.file
- state.image = Windows.URL.createObjectURL(file)
- // 或者:
- if (file) {
- var reader = new FileReader()
- reader.onload = function (evt) {
- state.image = evt.target.result
- }
- reader.onerror = function (evt) {
- console.error(evt)
- }
- reader.readAsDataURL(file)
- }
- }
比如在进行图片的本地显示时, 使用 createObjectURL 直接创建 url 对象进行展示或者使用 readAsDataURL 将其转化为 base64 进行展示.
当然在 electron 中一切都变得简单起来, 我们可以使用本地路径加载文件, 当然得进行一些小处理.
electron 本地文件加载
比如说我们已知一个本地图片的路径, 假设这个路径为下载文件夹中 C:\Users\Administrator\Downloads\1.PNG, 我们将这个地址赋值给 img 的 src:
- <a-upload
- :customRequest="customRequest"
- name="file"
- :showUploadList="false"
- :multiple="true"
- >
- <a-button>
- <upload-outlined></upload-outlined>
添加图片
- </a-button>
- </a-upload>
- <a-image
- :width="200"
- :height="200"
- :src="state.image"
- />
- function customRequest(fileData) {
- const path = fileData.file.path
- state.image = path
- }
这里的 path 就是本地文件的地址, 当你赋值之后发现图片并不能加载, 会报一个 net::ERR_UNKNOWN_URL_SCHEME 的错误, 这是由于直接添加本地路径的话, 加载文件实际上是通过 file:// 协议进行加载的, 默认情况下 chromium 并不能通过 file:// 协议来读取文件, 参考链接, 故并不能直接显示出来, 本来可以设置 chromium 启动参数
(--allow-file-access-from-files) 来解决这个问题, 但是比较遗憾 electron 并不吃这个一套:
- // 无效
- App.commandLine.appendSwitch('allow-file-access-from-files', true)
我们需要对这个本地路径进行处理, 让其不通过 file:// 协议加载, 那么如何实现呢?
我们可以通过 protocol 模块来注册自定义协议并拦截现有协议请求, 比如我们实现一个 atom:// 协议加载音乐文件进行播放:
主进程:
- App.whenReady().then(() => {
- // 这个需要在 App.ready 触发之后使用
- protocol.registerFileProtocol('atom', (request, callback) => {
- const url = request.url.substr(7)
- callback(decodeURI(path.normalize(url)))
- })
- })
渲染进程:
- <a-upload
- :customRequest="customRequest"
- name="file"
- :showUploadList="false"
- :multiple="true"
- >
- <a-button>
- <upload-outlined></upload-outlined>
添加本地音乐
- </a-button>
- </a-upload>
- <audio :src="state.audio" controls>
- </audio>
- function customRequest(fileData) {
- const path = 'atom:///' + fileData.file.path
- state.audio = path
- }
原来呢我们是直接赋值类似于 C:\Users\Administrator\Downloads\1.PNG, 我们在这个路径上加上 atom:/// 变为 atom:///C:\Users\Administrator\Downloads\1.PNG(Mac 同理, atom 是一样的), 当匹配到 atom 时, 就会拦截这个协议请求, 返回一个本地路径. 这里需要注意的一点是如果我们的路径有中文名, 那么获取的 url 是 encodeURI 编码后的, 我们在 callback 回调时需要用 decodeURI 进行解码.
注册了自定义协议之后, 我们只需在加载本地路径时, 在前面加上 atom:///(其他名也可, 自定义) 即可.
来源: https://segmentfault.com/a/1190000040174074