通过 Multer、Node 和 Express 通过 POST 请求将文件上传到后端服务器

时间:2021-05-26 15:19:09

标签: node.js angular express multipartform-data multer

我正在尝试通过 POST 请求从我的本地系统向后端服务器发送一个,但我无法在每次使用 --binary-data 而不是使用 --form 时都这样做。< /p>

这是我想使用 Node.js 构建的示例 curl:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

<table>
  <tr>
    <td>
      <span class="spanClassStatus">
      Missed
    </span>
      <span class="wrapperSpan">
      <i class="btn itagbtn" data-classschid="1" data-toggle="modal" data-target="#ModalUpdateClassStatus">Click</i>
    </span>
    </td>
  </tr>
  <tr>
    <td>
      <span class="spanClassStatus">
      Taken
    </span>
      <span class="wrapperSpan">
      <i class="btn itagbtn" data-classschid="2" data-toggle="modal" data-target="#ModalUpdateClassStatus">Click</i>
    </span>
    </td>
  </tr>
  <table>
    <!-- Modal -->
    <div class="modal fade" id="ModalUpdateClassStatus" tabindex="-1" role="dialog" aria-labelledby="modalLabelClassStatus">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h4 class="modal-title" id="modalLabelClassStatus">Update Class Status</h4>
            <button type="button" class="close d-block text-danger" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
          </div>
          <div class="modal-body">
            <form action="#" method="POST" id="modalForm">
              <div class="">
                <small>Select a new status for this class</small>
                <select name="selected_status_id" id="selected_status_id" required="required">
                  <option value="" selected="selected">Choose an item</option>
                  <option value="taken">Taken</option>
                  <option value="missed">Missed</option>
                </select>
                <!--added this hidden input-->
                <input type="hidden" name="classschid">
              </div>
              <i class="fa fa-spinner fa-pulse fa-3x fa-fw text-primary d-none" id="statusSpinner"></i>
              <span class="sr-only">Please wait ...</span>
              <button type="submit" id="editClassStatusBtn" class="btn btn-success mt-2" style="font-size:0.9rem;">Update Status</button>
            </form>

          </div>
          <!-- end of modal-body -->
        </div>
      </div>
    </div>

这是component.html:

curl --location --request POST 'some-endpoint' \
--form 'file=@"/Users/name/Desktop/sample.csv"'

这是component.ts:

<form (ngSubmit)="handleCsvClick()" encrypt="multipart/form-data">
 <input
  type="file"
  name="file-input"
  #fileInput
  [disabled]="requestInProgess"
  (change)="handleFilePick()"
/>
<button
class="upload-btn btn-reset"
type="submit"
>
Upload CSV File
</button>
</form>

Node.js

路由器文件:

 handleCsvClick(){
    const file = this.fileInputRef.nativeElement.files[0];
    const form = new FormData();
    form.append("file", file);
    const endpoint = `/api/upload-csv`;
    this.http.post(endpoint,form).subscribe((data) => {
      console.log(data);
    });
  }

控制器:

const path = require('path');
const express = require("express");
const cookieParser = require("cookie-parser");
const multer = require('multer');
const router = express.Router();
const uuidv4 = require('uuid/v4');
const advisoryController = require("../controllers/advisoryController");
const { UPLOADS_PATH } = require('../config/environment');
const storage = multer.diskStorage({
  destination: UPLOADS_PATH,
  filename: function(_, file, cb) {
    const fileExt = path.extname(file.originalname);
    cb(null, `_csvUploadFile_${uuidv4()}${fileExt}`);
  },
});
const upload = multer({ storage });

router.post("/upload-csv", upload.single("file"), (req, res) => {
  advisoryController
    .uploadCSV(req.file)
    .then(response => res.send(response.data))
    .catch(error => {
      res.status(error.status || 500).send("Something went wrong");
      console.log(error);
    });
});

在所有这些之后构建的 curl 以 --data-binary 而不是 --form 的形式出现:

const axios = require("axios");
const { advisoryList } = require("../config/apiConfig");
const fs = require('fs');
const request = require('request');
const FormData = require('form-data');

function uploadCSV(file) {
  let requestUrl = advisoryList.uploadCSV.url;
  const { path } = file;
  const fileUpload = fs.createReadStream(path);
  return new Promise((resolve, reject) => {
    axios
    .post(requestUrl, fileUpload, {headers: {
      'Content-Type': 'multipart/form-data'
    }})
    .then(response => {
      resolve(response.data);
    })
    .catch(error => {
      reject(error)
      console.log("CURL: ", error.request.toCurl());
    });
  })
}

代替:

curl 'someendpoint' -H 'accept: application/json, text/plain, */*' -H 'content-type: multipart/form-data' -H 'user-agent: axios/0.18.0' --data-binary $'userId,name,age,city\n29298914,vish,30,Bangalore\r\n0\r\n\r\n' --compressed

任何帮助将不胜感激。提前致谢。

1 个答案:

答案 0 :(得分:1)

要在 Node.js 中使用 axios 发送文件,您需要:

  1. 使用 form-data 库创建表单
  2. 使用 getHeaders() 设置表单中的请求标头

将您的代码更改为:

const form = new FormData();
form.append('file', fileUpload, path); // 3rd argument is the file name

// Send other fields along with the file
form.append('title', 'Q1 2021');
form.append('description', 'An utterly interesting report');

// Get form headers to pass on to axios
const formHeaders = form.getHeaders();

// Sending a file with axios
axios.post(requestUrl, form, { headers: { ...formHeaders } });

您的问题启发了我将此答案转化为一篇文章 — Send a File With Axios in Node.js。它涵盖了一些常见的陷阱,您将学习如何发送存储为缓冲区或来自流的文件。