簡體   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