电子上传有进展

Electron upload with progress

我有一个 Electron 应用程序,它能够在渲染器进程中通过 HTTP 将非常大的文件 上传到服务器,而无需用户输入。我决定使用 axios 作为我的 HTTP 客户端,它能够检索上传进度,但我遇到了一些问题。

浏览器支持的 js 和 Node.js 在某些时候彼此并不“友好”。我使用 fs.createReadStream 函数来获取文件,但 axios 不明白 ReadStream 对象是什么,我无法通过管道传输(他们的 GitHub 问题选项卡上有几个主题,但是到现在为止什么都没做)这个流到 FormData (我应该把我的文件放在里面)。

我最终使用 fs.readFileSync,然后使用 form-data 模块及其 getBuffer() 方法,但现在我的文件在上传之前完全加载到内存中,并且我的文件有多大杀死电子进程。

谷歌搜索我发现了 request 库,该库实际上能够通过管道传输流来请求,但它已被弃用,不再受支持,显然我无法从中获取上传进度。

我 运行 别无选择。你如何在没有用户输入的情况下使用 Electron 上传文件(因此没有文件输入)而不是预先将它们加载到内存中?

P.S。在 form-data github 页面上有一段代码解释了如何使用 axios 上传文件流,但它不起作用,没有发送任何内容并按照一个问题主题建议降级库也没有帮助...

const form = new FormData();
const stream = fs.createReadStream(PATH_TO_FILE);
 
form.append('image', stream);
 
// In Node.js environment you need to set boundary in the header field 'Content-Type' by calling method `getHeaders`
const formHeaders = form.getHeaders();
 
axios.post('http://example.com', form, {
  headers: {
    ...formHeaders,
  },
})
.then(response => response)
.catch(error => error)

我能够解决这个问题,希望它能帮助遇到同样问题的任何人。

由于 request 已弃用,我查找了替代方案并找到了 got.js 用于 NodeJS HTTP 请求。它支持Streamfs.ReadStream

您还需要 form-data,它允许将流放入 FormData 并将其分配给一个键。

下面的代码解决了我的问题:


import fs from 'fs'
import got from 'got'
import FormData from 'form-data'

const stream = fs.createReadStream('some_path')

// NOT native form data
const formData = new FormData()

formData.append('file', stream, 'filename');

try {
    const res = await got.post('https://my_link.com/upload', {
        body: formData,
        headers: {
            ...formData.getHeaders() // sets the boundary and Content-Type header
        }
    }).on('uploadProgress', progress => {
        // here we get our upload progress, progress.percent is a float number from 0 to 1
        console.log(Math.round(progress.percent * 100))
    });

    if (res.statusCode === 200) {
        // upload success
    } else {
        // error handler
    }
} catch (e) {
    console.log(e);
}

在 Electron 渲染器进程中完美运行!