如何从浏览器发送一个大文件到 Node.js 服务器?

How can I send a big file from the browser to the Node.js server?

我正在尝试使用 data: URL 从客户端向服务器发送图像。我读取上传的图片并向服务器发送数据的功能非常简单:

getTags = event => {
    const file = event.target.files[0];

    if (!file.type.match('image.*')) {
      return;
    }

    const reader = new FileReader();

    reader.onload = (theFile => {
      return (e) => {
        this.sendDataToServer(e.target.result, theFile.type);
      };
    })(file);

    reader.readAsDataURL(file);
  }

sendDataToServer = (data, fileType) => {
    const options = {
      method: 'POST',
      headers: {
        'Content-Type': fileType,
      },
      body: JSON.stringify({data}),
      cache: 'default'
    }
    fetch('http://localhost:5000/img', options)
    .then(res =>  res.text())
    .then(body => {
        console.log(body);
    });
  }

如果我在将其放入 sendDataToServer 之前打印 e.target.result,我会看到一个有效的 data: URL

那么,我的服务器:

const app = express();
app.use(cors());
app.use(helmet());
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

app.post('/img', (req, res, next) => {
  const data = decodeURIComponent(req.body.data);
  console.log(data);
  // ... 

但是在 Chrome DevTools 的网络选项卡中,我看到:

Request URL:http://localhost:5000/img
Request Method:OPTIONS
Status Code:204 No Content
Remote Address:52.15.183.149:80
Response Headers
view source
Access-Control-Allow-Headers:content-type
Access-Control-Allow-Methods:GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin:*
Date:Sat, 25 Mar 2017 20:18:09 GMT
X-Powered-By:Express
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
DNT:1
Host:b580f823.ngrok.io
Origin:http://localhost:3000
Referer:http://localhost:3000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.1165

在服务器上我的 console.log 只打印 undefined。不明白为什么会这样。我的错误在哪里?

问题中显示 client-side 信息的所有内容都表明它在客户端工作正常。

所以看来服务器端一定有问题,不是由任何客户端错误引起的。

我这么说是因为:

  1. 请求的开发工具片段显示 Request Method:OPTIONSwhich is expected 因为你的 POSTContent-Type header 而不是 application/x-www-form-urlencoded, multipart/form-data, 或 text/plain.

  2. 在这种情况下,您的浏览器首先发送 CORS 预检 OPTIONS 请求,并期望返回 Access-Control-Allow-Headers:content-type 响应 header 以及 Access-Control-Allow-Methods 包括 POST, 和 Access-Control-Allow-Origin.

  3. 问题中的 devtools 片段显示它按预期获得了所有这些,因此它应该发送实际的 POST。您没有显示那个 POST 的开发工具片段,但如果您的浏览器没有执行实际的 POST,它会向开发工具控制台记录某种错误。

所以除非我遗漏了什么,否则你的 client-side 代码中没有错误,因此一定是服务器端出现了一些问题导致它失败。