使用multer / Angular

问题描述

错误:多部分:未找到边界

我想添加一些带有角度的文本文件文件: 这是我的服务:

src / app / services / web.service.ts

import { Injectable } from '@angular/core';
import { HttpClient,HttpHeaders } from '@angular/common/http';


const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'multipart/form-data'
  })
}

@Injectable({
  providedIn: 'root'
})
export class WebService {

  devUri:string = 'http://localhost:4000';
  constructor(private http:HttpClient) { }
    
  post(uri:string,object: Object){
    console.log(object);
    return this.http.post(`${this.devUri}/${uri}`,object,httpOptions);
  }

}

显示Error: Multipart: Boundary not found 在有人写下“仅删除'Content-Type':'multipart / form-data'之前它将起作用,但不会成功! 当我删除它时,我的req.files = [](还有一些变体,它等于未定义)。 这是我的路线(虽然不满,但不需要更多):

routes / api / messages.js

const { initStorage,initUpload } = require('../../modules/multerModule');

const conn = mongoose.connection;
Grid.mongo = mongoose.mongo;
// Init gfs
let gfs;

conn.once('open',() => {
  // Init stream
  gfs = Grid(conn.db);
  gfs.collection(collectionName);
});

const collectionName = 'messages';
const bucketName = 'messages';

const storage = initStorage(conn,bucketName);

const upload = initUpload(storage);

router.post('/',upload.any(),(req,res) => {

  console.log(req.files);
  console.log(req.body);

...
}

这是我来自multerModule的函数(它们都可以在react / redux,app上运行,但不能在Angular上运行):

modules / multerModule.js:

const path = require('path');
const multer = require('multer');
const crypto = require('crypto');
const GridFsstorage = require('multer-gridfs-storage');

// Create storage engine
const initStorage = (conn,bucketName) => new GridFsstorage({
  db: conn,file: (req,file) => {
    return new Promise((resolve,reject) => {
      crypto.randomBytes(16,(err,buf) => {
        if (err) {
          return reject(err);
        }
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,bucketName: bucketName
        };
        resolve(fileInfo);
      });
    });
  }
});

// Create upload module
const initUpload = (storage) => multer({
  storage: storage,fileFilter: function (req,file,callback) {
    const ext = path.extname(file.originalname);
    if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
      return callback(new Error('Only images are allowed'))
    }
    callback(null,true)
  }
});

module.exports = { initStorage,initUpload };

当然,稍后当我尝试使用req.files(destructurize或其他方法)时,我得到了错误,因为它是未定义或空数组。在req.body中,还显示了消息字段:

[Object: null prototype] {
  messages: '[object File]',content: 'dsada',path: 'undefined',fileImage: 'true'
}

最后两件事是server.js和onSubmit函数

server.js

...
const bodyParser = require('body-parser');
// #6 Initialize an Express application 
const app = express();

app.use(cors()); 

app.use(bodyParser.urlencoded({limit: '50mb',extended: true}));
app.use(bodyParser.json({limit: '50mb',extended: true}));

const db = process.env.mongoURI;

// Connect to Mongo
mongoose 
  .connect(db,{ 
    useNewUrlParser: true,useCreateIndex: true,useUnifiedTopology: true,useFindAndModify: false }) // Adding new mongo url parser 
  .then(() => console.log('MongoDB Connected...')) 
  .catch(err => console.log(err)); 
...

OnSubmit函数

src / app / components / Message / add-message / add-message.ts

onSubmit() {

    if( this.fileImage){
      const message = new FormData();
      

      console.log(this.files[0]);
      message.append('messages',this.files);

      console.log(typeof(JSON.stringify(this.fileImage)));
      message.append('content',this.content);
      message.append('fileImage',JSON.stringify(this.fileImage));
  

this.addMessage.emit(message);
}
else{
  const message = {
    content: this.content,fileImage: this.fileImage,path: this.path
  }
  this.addMessage.emit(message);
}

}

经过几次尝试,我又遇到另一个错误(现在我不在HttpClient模块中包括httpOptions,并且附加到FormData()的文件数据与react-redux / node应用程序中的相同):

Error: The database connection must be open to store files
    at GridFsstorage._handleFile

问题在于,相同的代码在redux应用程序中可以正常工作,但在angular语言中不能正常工作。

解决方法

好的,我在console.log上找到了一些东西:

conn.once('open',() => {
  // Init stream
  gfs = Grid(conn.db);
  
  gfs.collection(collectionName);
});

const collectionName = 'messages';
const bucketName = 'messages';

console.log(conn); 
...

我发现了一个区别:

在angular应用程序上,我发现了这一点:

models: { user: Model { user } }

我有三种模式:用户,帖子和消息。

在React应用程序上,我发现:

 models: {
     announcement: Model { announcement },user: Model { user },slide: Model { slide },content: Model { content },insurance: Model { insurance },contact: Model { contact }
   }

,这是正确的,因此看来我的存储中未包含所有型号的路线。 我不知道为什么,但是看来,这就是问题所在。 modelSchemas属性也是如此。 即使在我评论此路由(app.use(/ auth))时,它仍然仅包含userSchema和UserModel。

在连接server.js之后,我登录了“ promise”。

// Connect to Mongo
const promise = mongoose 
  .connect(db,{ 
    useNewUrlParser: true,useCreateIndex: true,useUnifiedTopology: true,useFindAndModify: false }) // Adding new mongo url parser 
  .then(() => console.log('MongoDB Connected...')) 
  .catch(err => console.log(err)); 

  console.log(promise);

仅获得一个模型和模式(即使我有三个模型:发布,用户,消息):

Promise { <pending> }
NativeConnection {
  base: Mongoose {
    connections: [ [Circular] ],models: { user: Model { user } },modelSchemas: { user: [Schema] },options: { pluralization: true,[Symbol(mongoose:default)]: true },_pluralize: [Function: pluralize],Schema: [Function: Schema] {
      reserved: [Object: null prototype],Types: [Object],ObjectId: [Function]
    },model: [Function],plugins: [ [Array],[Array],[Array] ]
  },collections: {
    users: NativeCollection {
      collection: null,Promise: [Function: Promise],_closed: false,opts: [Object],name: 'users',collectionName: 'users',conn: [Circular],queue: [],buffer: true,emitter: [EventEmitter]
    }
  },config: { autoIndex: true,useFindAndModify: false },replica: false,options: null,otherDbs: [],relatedDbs: {},states: [Object: null prototype] {
    '0': 'disconnected','1': 'connected','2': 'connecting','3': 'disconnecting','99': 'uninitialized',disconnected: 0,connected: 1,connecting: 2,disconnecting: 3,uninitialized: 99
  },_readyState: 2,_closeCalled: false,_hasOpened: false,plugins: [],id: 0,_listening: false,_connectionString: 'Sorry,but cannot pass :)',_connectionOptions: {
    useNewUrlParser: true,promiseLibrary: [Function: Promise],driverInfo: { name: 'Mongoose',version: '5.10.3' }
  },client: MongoClient {
    _events: [Object: null prototype] {},_eventsCount: 0,_maxListeners: undefined,s: {
      url: 'sorry,options: [Object],dbCache: Map {},sessions: Set {},writeConcern: undefined,namespace: [MongoDBNamespace]
    },[Symbol(kCapture)]: false
  },'$initialConnection': Promise { <pending> },then: [Function],catch: [Function],_events: [Object: null prototype] {
    open: [Function: bound onceWrapper] { listener: [Function] }
  },_eventsCount: 1