javascript - 使用 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 = [](这里还有一些变化等于未定义)。这是我的路线(不完整,但不需要更多):
路线/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):
模块/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 };
Ofcourse 后来当我尝试使用 req.files(destructurize 或其他) 我得到错误,因为它是未定义或空数组。在 req.body 中,还显示了 messages 字段:
[Object: null prototype] {
messages: '[object File]',
content: 'dsada',
path: 'undefined',
fileImage: 'true'
}
最后两件事是 server.js 和 onSubmit 函数:
服务器.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 } }
我有三个模型:用户、帖子和消息。
在反应应用程序上,我发现:
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 之后,我记录了“承诺”。
// 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);
并且只得到一个模型和模式(即使我有三个模型:post、user、message):
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], [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]
}
},
models: { user: Model { user } },
config: { autoIndex: true, useCreateIndex: 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,
useUnifiedTopology: true,
promiseLibrary: [Function: Promise],
driverInfo: { name: 'Mongoose', version: '5.10.3' }
},
client: MongoClient {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
s: {
url: 'sorry, but cannot pass :)',
options: [Object],
promiseLibrary: [Function: Promise],
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
推荐阅读
- c# - 将搜索栏对齐到右中心
- swift - Swift 中的自定义 Instagram 登录页面
- mysql - Flask 使用 MySQL 将数据插入数据库
- excel - Excel - 在表之间创建一对一的关系
- python - 如何为 Python 3 安装`cv`?
- git - git cherry-pick 以编程方式从合并中挑选
- angular - 我从 GET 方法收到的数据没有在 html 页面上更新
- bluetooth - Raspberry Pi 的蓝牙网状网络
- math - 来自 OpenGL 的标准化设备坐标金属
- c# - 即使 XML 有数据,C# 中的 XML 反序列化也会返回空数组