关于Nodejs图片保存的问题,纠结了好久急求大神解答
关于Nodejs图片保存的问题,纠结了好久急求大神解答
我想用Node实现图片文件的存储,然后通过IOS客户端上传。在网上找了好久,一直没能解决问题
app.post('/avatar', function(req, res) {
console.log(req);
if(!(req.query.username)) {
return res.json({
code: 0,
msg: '参数信息不完整'
});
}
// 获得文件的临时路径
var tmp_path = req.files.file.path;
console.log(tmp_path);
// 指定文件上传后的目录 - 示例为"avatars"目录。
var target_path = '../avatars/' + req.files.file.name;
// 移动文件
fs.rename(tmp_path, target_path, function(err) {
if (err) {
return res.json({
code: 0,
msg: err.toString()
});
}
// 删除临时文件夹文件,
fs.unlink(tmp_path, function(err) {
if (err) throw err;
});
});
});
ios客户端上传代码如下
NSString *username = [ZKConstValue getLoginStatus];
if (!username && [username isEqualToString:@""]) {
NSLog(@"ERROR: postImage,username is valide");
return;
}
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/avatar_%@.png", username]];
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:pngPath atomically:YES];
MKNetworkEngine *networkEngine = [[MKNetworkEngine alloc] initWithHostName:SERVER_URL_WITHOUT_HTTP];
MKNetworkOperation *networkOperation = [networkEngine operationWithPath:[NSString stringWithFormat:@"avatar?username=%@", username] params:nil httpMethod:@"POST"];
[networkOperation addFile:pngPath forKey:@"file" mimeType:@"image/png"];
[networkOperation setFreezable:YES];
[networkOperation addCompletionHandler:^(MKNetworkOperation *completedOperation) {
NSString *responseString = [completedOperation responseString];
NSLog(@"server response: %@",responseString);
} errorHandler:^(MKNetworkOperation *completedOperation, NSError *error) {
NSLog(@"Upload avatar error: %@", error);
}];
[networkEngine enqueueOperation:networkOperation];
Request
curl -X POST “http://192.168.0.100:1337/avatar?username=dbngb” -F “file=@/var/mobile/Containers/Data/Application/1B756503-C0BC-4A36-8C76-480EE8111C1D/Documents/avatar_dbngb.png;type=image/png”
这样上传后在服务端打印req.files是undefine,也就是获取不到上传的文件。求帮帮忙!!!
针对你遇到的问题,主要是在处理文件上传时,req.files
未被正确解析。这通常是因为缺少必要的中间件来处理 multipart/form-data 类型的请求。在 Node.js 中,常用的中间件有 multer
。
解决方案
首先安装 multer
:
npm install multer --save
接下来,我们需要对服务器端的代码进行修改以使用 multer
来处理文件上传。
修改后的服务器端代码
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
// 设置 Multer 存储配置
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, 'avatars')); // 文件存储目录
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname)); // 文件名
}
});
const upload = multer({ storage: storage });
app.post('/avatar', upload.single('file'), function(req, res) {
if (!(req.query.username)) {
return res.json({
code: 0,
msg: '参数信息不完整'
});
}
const target_path = path.join(__dirname, 'avatars', req.file.filename);
// 返回成功响应
res.json({
code: 1,
msg: '文件上传成功',
filePath: target_path
});
});
iOS 客户端代码
你的 iOS 客户端代码看起来已经基本正确,但确保你使用的网络库(如 MKNetworkEngine
)能够正确处理文件上传。
NSString *username = [ZKConstValue getLoginStatus];
if (!username || [username isEqualToString:@""]) {
NSLog(@"ERROR: postImage, username is invalid");
return;
}
UIImage *image = ...; // 获取你的图像
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/avatar_%@.png", username]];
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:pngPath atomically:YES];
MKNetworkEngine *networkEngine = [[MKNetworkEngine alloc] initWithHostName:SERVER_URL_WITHOUT_HTTP];
MKNetworkOperation *networkOperation = [networkEngine operationWithPath:[NSString stringWithFormat:@"avatar?username=%@", username] params:nil httpMethod:@"POST"];
[networkOperation addFile:pngPath forKey:@"file" mimeType:@"image/png"];
[networkOperation setFreezable:YES];
[networkOperation addCompletionHandler:^(MKNetworkOperation *completedOperation) {
NSString *responseString = [completedOperation responseString];
NSLog(@"Server response: %@", responseString);
} errorHandler:^(MKNetworkOperation *completedOperation, NSError *error) {
NSLog(@"Upload avatar error: %@", error);
}];
[networkEngine enqueueOperation:networkOperation];
总结
通过引入 multer
,我们可以更好地处理文件上传。同时,确保客户端发送的请求格式符合服务器期望的格式。以上代码应能解决你遇到的问题,并且提供了更清晰的文件上传流程。
你有加bodyparser或者formidable之类的中间件吗 ps lz好厉害啊,移动开发前后端通吃啊
req.files是undefined肯定是因为你没有安装中间件。没捕获post请求
我已经加了bodyparser中间件,捕获post请求是什么意思
app.use(express.multipart({keepExtensions: true, uploadDir: ‘your_upload_path’})); 这是我express 3 的一个node.js的一段上传用得代码,楼主在app.js中是怎么配置的?
3楼正解,express 4.x以后我都是用的 connect-multiparty 中间件了来获取 req.files 了。
你的问题主要在于请求中 req.files
无法正确解析。通常这可能是因为缺少必要的中间件来处理文件上传,比如 multer
。
首先,你需要安装 multer
中间件:
npm install multer
然后,你可以使用 multer
来处理文件上传。以下是修改后的代码示例:
Node.js 服务端代码
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');
const app = express();
// 配置 multer 存储策略
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './avatars'); // 存储文件的目录
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname); // 使用时间戳加上原始文件名作为新文件名
}
});
const upload = multer({ storage: storage });
app.post('/avatar', upload.single('file'), function (req, res) {
if (!req.query.username) {
return res.json({
code: 0,
msg: '参数信息不完整'
});
}
const target_path = path.join(__dirname, 'avatars', req.file.filename);
// 检查目标路径是否存在,如果不存在则创建目录
if (!fs.existsSync(path.dirname(target_path))) {
fs.mkdirSync(path.dirname(target_path), { recursive: true });
}
fs.rename(req.file.path, target_path, function (err) {
if (err) {
return res.json({
code: 0,
msg: err.toString()
});
}
fs.unlink(req.file.path, function (err) {
if (err) throw err;
});
res.json({
code: 1,
msg: '文件上传成功'
});
});
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
iOS 客户端代码
func uploadAvatar(image: UIImage, username: String) {
let pngPath = NSTemporaryDirectory().appending("avatar_\(username).png")
let imageData = image.pngData()
imageData?.write(toFile: pngPath, atomically: true)
let networkEngine = MKNetworkEngine(hostName: SERVER_URL)
let networkOperation = networkEngine.operationWithPath("/avatar", params: ["username": username], httpMethod: "POST")
networkOperation.addFile(pngPath, forKey: "file", mimeType: "image/png")
networkOperation.completionBlock = {
let responseString = networkOperation.responseText
print("server response: \(responseString)")
}
networkOperation.errorBlock = { error in
print("Upload avatar error: \(error)")
}
networkEngine.queue(networkOperation)
}
通过以上代码,你可以在 Node.js 服务端正确地处理文件上传,并将文件保存到指定的目录中。同时,iOS 客户端也可以正确地发送文件数据到服务器。