Angular SSR-通过Express API将FormData发送到节点服务器

时间:2019-10-30 12:54:42

标签: node.js angular express mean-stack

在MEAN堆栈应用程序中,我需要将FormData(连同文件)发送到后端服务器,并将这些信息相应地保存到MongoDB。这是Angular组件方法,它提交Form-

  saveProduct(formDirective): void {
    let formData: FormData = new FormData();
    formData.append("name", formModel.nameFormControl as string);
    formData.append("price", formModel.priceFormControl as string);
    formData.append("currency", formModel.currencyFormControl as string);
    formData.append("url", formModel.urlFormControl as string);
    formData.append("description", formModel.descriptionFormControl as string);

    if (this.fileToUpload !== null) {
      formData.append("uploadFile", this.fileToUpload, this.fileToUpload.name);
    }

    let headers = new Headers();
    headers.append("Content-Type", "multipart/form-data");
    headers.append("Accept", "application/json");
    headers.append("Authorization", this.jwtToken);

    this.productsService.addProduct(formData, headers).subscribe(res => {.......});
  }

  handleFileInput(files: FileList) {
    if (files.length > 0) {
      this.fileToUpload = files.item(0);
    }
  }

这里是Component HTML for Form文件,其中File信息已完美添加到FormData。经过测试和验证-

<input
  #file
  formControlName="imageFormControl"
  id="file"
  type="file"
  accept="image/x-png,image/gif,image/jpeg"
  (change)="handleFileInput($event.target.files)"
/>

这里是Service方法,它将FormData发送到API-

  addProduct(formData: FormData, headers: any): any {
    formData.forEach(entries => console.log(entries));
    return this.http
      .post(environment.apiURL + "/admin/product/save", formData, headers)
      .map(res => res);
  }

console中,我得到FormDataFile信息。

让我们来看看我遇到问题的Express API

我在Angular SSR(server.ts)中创建了一个API路由。以下是将API路由添加到server.ts文件中的方法-

import { routes } from './api/routes';

app.use('/api', routes);

API文件结构位于以下层次结构中-

api---
   ---functions
      admin.functions.ts
   ---routes
      admin.routes.ts
   ---routes.ts

这是我的routes.ts文件-

import { Router } from 'express';

import AdminRoutes from './routes/admin.route';
export const routes = new Router();

// ADMIN ROUTES
routes.use('/admin', AdminRoutes);

export default routes;

这是routes/admin.routes.ts代码-

import {
  Router,
} from 'express';

import AdminAPI from '../functions/admin.functions';

const routes = new Router();

routes.route('/product/save').post(AdminAPI.saveProduct);

export default routes;

这是functions/admin.functions.ts代码-

import axios from 'axios';

class AdminAPI {

    async saveProduct(req, res, next) {
        try {
            console.log('admin save bot', `${SERVER}/admin/product/save`);
            console.log('body', req.body); <- Here I expected FormData
            const response = await axios.post(`${SERVER}/admin/product/save`, req.body, {headers: req.headers});
            res.json(response.data);
        } catch (error) {
            next(error);
        }
    }
}

export default new AdminAPI();
  

此处要求正文为空。我在req.body中所期望的   FormData,但我没有得到。我需要发送FormData   通过Axios

到后端的信息

作为参考,我们来看一下当我不使用Angular SSR时可以正常工作的服务器代码

exports.admin_save_default_product = function(req, res, next) {
  req.pipe(req.busboy);

  var product = {};

  req.busboy.on("field", function(key, value, keyTruncated, valueTruncated) {
    product[key] = value;
  });

  req.busboy.on("file", function(fieldname, file, filename) {
    let file_type = filename.split(".").pop();

    if (
      file_type === "png" ||
      file_type === "gif" ||
      file_type === "jpeg" ||
      file_type === "jpg"
    ) {
      let file_stream;
      let new_filename = Date.now() + "." + file_type;
      let filePath = path.join(__basedir, "/server/images", new_filename);

      fileUploaded = true;

      product.image = new_filename;

      file_stream = fs.createWriteStream(filePath);

      file.pipe(file_stream);

      file_stream.on("close", function() {
        console.log("file uploaded!");
      });
    }
  });

  req.busboy.on("finish", function() {
    let timestamp = new Date();
    let current_user_id = req._id;

    let current_user_promise = userModel.find_user_by_id(current_user_id);

    current_user_promise
      .then(function(result) {
        product.author = result;
        product.source = process.env.PRODUCT_DEFAULT_SOURCE;
        product.created_time = timestamp;
        product.bot_enabled = 0;

        let save_product_promise = productModel.save_product(product);

        save_product_promise
          .then(function(result) {
            var response_information = {
              message: "success"
            };

            res.status(201).json(response_information);
          })
          .catch(function(err) {
            res.status(500).json({ error: err });
          });
      })
      .catch(function(err) {
        res.status(500).json({ error: err });
      });
  });
};

此处busboy file and field个事件不起作用,因为fieldfile为空。但是finish事件运行正常。

  

因此,我面临的主要问题-无法执行Axios POST请求   可以将FormData发送到后端

谢谢!

0 个答案:

没有答案