繁体   English   中英

如何从 React 应用程序将 Png 或 Jpeg 图像作为二进制文件发送到 node.js 服务器?

[英]How to send a Png or Jpeg image as binary to node.js server from react app?

我正在尝试将文件从反应 Web 应用程序发送到 node.js 服务器。

我从文件类型的 html 输入开始,一旦用户上传他们的文件,我就会向我的 Node.js 服务器触发一个发布请求。

一旦进入我的 Node.js 服务器,我需要向第 3 方 API (Twilio) 发送一个发布请求

第 3 方 API 需要我的文件作为二进制数据。

注意:来自文档“POST 的正文或内容必须是二进制格式的文件本身。”

这是下面的 React 组件

import React, { Fragment, useState, useRef } from "react";
import { Col, Button, Media, Card, CardBody } from "reactstrap";
import { useSelector, useDispatch } from "react-redux";
import { attachMMS } from "../../../actions/index";
import cloudUpload from "../../../assets/img/icons/cloud-upload.svg";

const InsertMMS = ({
  showFileModal,
  setShowFileModal,
  showInsertMMSModal,
  setShowInsertMMSModal,
  uploadMMS,
  setUploadMMS,
}) => {
  const InputFile = useRef(null);
  const [userMMS, setUserMMS] = useState();
  const [highlighted, setHighlighted] = useState(false);
  const dispatch = useDispatch();

  const attachMMSCreate = useSelector((state) => state.attachMMSCreate);

  const manualMMSUpload = (e) => {
    console.log("manualMMSUpload ran");
    e.preventDefault();
    if (e.target.files[0].name) {
      console.log("file", e.target.files[0]);
      getBinary(e.target.files[0]);
      setUserMMS(e.target.files[0].name);
    }
  };

  const getBinary = (file) => {
    const reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.onload = () => {
      setUploadMMS({ file: file, fileType: file.type });
    };
  };

  const handleInputChange = ({ value, name }) =>
    setUploadMMS({ ...uploadMMS, [name]: value });

  const onButtonClick = (e) => {
    e.preventDefault();
    InputFile.current.click();
  };

  return (
    <Fragment>
      <Card>
        <CardBody className="fs--1 font-weight-normal p-4">
          <h4 className="mb-1 mt-3 text-center"></h4>
          <div>
            <input
              type="file"
              onChange={(e) => manualMMSUpload(e)}
              accept=".gif, .png, .jpeg"
              ref={InputFile}
              className="d-none"
            />
            <div
              className={`mb-2 p-3 border-dashed border-2x border-300 bg-light rounded-soft text-center cursor-pointer ${
                highlighted ? " border-800" : ""
              }`}
              onClick={(e) => onButtonClick(e)}
              onDragEnter={() => {
                setHighlighted(true);
              }}
              onDragLeave={() => {
                setHighlighted(false);
              }}
              onDragOver={(e) => {
                e.preventDefault();
              }}
              onDrop={(e) => {
                e.preventDefault();
              }}
            >
              <Fragment>
                <Media className=" fs-0 mx-auto d-inline-flex align-items-center">
                  <img src={cloudUpload} alt="" width={25} className="mr-2" />
                  <Media>
                    <p className="fs-0 mb-0 text-700">
                      {userMMS ? userMMS : "Upload your File"}
                    </p>
                  </Media>
                </Media>
                <p className="mb-0 w-75 mx-auto text-500">
                  Supports: .gif, .png, .jpeg{" "}
                </p>
              </Fragment>
            </div>
          </div>
          <p className="fs-0 text-center">multi-media message</p>
          <Col className="text-center">
            <Button
              disabled={!uploadMMS}
              color="primary"
              onClick={() => {
                return (
                  dispatch(attachMMS(uploadMMS)),
                  setShowInsertMMSModal(!showInsertMMSModal),
                  setShowFileModal(!showFileModal)
                );
              }}
              className="my-3 text-white"
            >
              {attachMMSCreate.loading ? "...processing" : "Attach MMS"}
            </Button>
          </Col>
        </CardBody>
      </Card>
    </Fragment>
  );
};

export default InsertMMS;

这是从 React 向 Node.js 服务器发出 POST 请求时调用的 Action

export const attachMMS = (uploadMMS) => async (dispatch) => {
  console.log("body of attachMMS in actions", uploadMMS);
  try {
    dispatch({ type: ATTACH_MMS_CREATE_REQUEST });
    await axios({
      url: "http://localhost:5000/mms",
      method: "POST",
      data: uploadMMS.file,
      withCredentials: true,
    }).then((res) =>
      dispatch({ type: ATTACH_MMS_CREATE_SUCCESS, payload: res })
    );
  } catch (error) {
    console.log(error);
    dispatch({
      type: ATTACH_MMS_CREATE_FAIL,
      payload:
        error.message && error.response.data.message
          ? error.response.data.message
          : error.message,
    });
  }
};

这是被触发的 Node.js 路由

module.exports = (router) => {
  router.route("/mms").post(twilCtrl.createMediaMMSResource);
};

这是被调用的 Node.js 函数

const createMediaMMSResource = async (req, res) => {
  try {
    const { subActServiceSid, subActAuthToken, convoServiceSid } = req.user;
    let mediaResource;

    await axios({
      url: `https://mcs.us1.twilio.com/v1/Services/${convoServiceSid}/Media`,
      method: "POST",
      data: req.body, // this needs to be the file itself in binary format
      headers: {
        "Content-Type": "image/png",
      },
      auth: { username: subActServiceSid, password: subActAuthToken },
      withCredentials: true,
    }).then((res) => {
      console.log(
        "res from first post request to twilio with fileData",
        res.data
      );
      return (mediaResource = {
        mediaUrl: res.data.url,
        serviceSid: res.data.service_sid,
        mediaSid: res.data.sid,
      });
    });
    res.status(201).json(mediaResource);
  } catch (err) {
    console.log(err);
  }
};

这是我从客户那里得到的回复......

有没有人看到这个问题? 我似乎无法理解如何将“二进制”数据发送到 node.js 服务器.....

在此处输入图像描述

可以从浏览器发送二进制数据,您可以通过express.raw()中间件在 Express 中处理这些数据,但是我会改为执行以下操作...

  1. 通过FormData将文件上传到您的 Express 服务 这通常是浏览器执行二进制上传的方式,而 Axios 等实用程序使其变得更加容易。

     const manualMMSUpload = (e) => { if (e.target.files.length > 0) { const file = e.target.files[0]; setUploadMMS({ file, fileType: file.type }); setUserMMS(file.name); } };
     // export const attachMMS = (uploadMMS) => async (dispatch) => { // ... // use axios.postForm() const res = await axios.postForm("http://localhost:5000/mms", { file: uploadMMS.file }, { withCredentials: true }); // do you actually need cookies? dispatch({type: ATTACH_MMS_CREATE_SUCCESS, payload: res}) // ...

    仅供参考,除非您依赖 cookie,否则您不需要withCredentials

    如果您使用的是没有postForm的旧版本 Axios,请使用以下命令

    const data = new FormData(); data.append("file", uploadMMS.file); const res = await axios.post("http://localhost:5000/mms", data);
  2. 使用Multerexpress-fileupload中间件在 Express 服务中处理文件上传。

     const fileUpload = require('express-fileupload'); router.route('/mms').post(fileUpload(), twilCtrl.createMediaMMSResource)
  3. 将上传的文件缓冲区传递给上游 API。

     const response = await axios.post( `https://mcs.us1.twilio.com/v1/Services/${convoServiceSid}/Media`, req.files.file.data, // here's the buffer { auth: { username: subActServiceSid, password: subActAuthToken }, headers: { "content-type": req.files.file.mimetype, }, } );

    这应该将文件数据缓冲区作为原始二进制数据上传。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM