Nodejs异步上传图片失败,求教

Nodejs异步上传图片失败,求教

我用 Node.js 的 app.use(express.bodyParser()); 函数实现了提交表单上传图片,但是我想通过 Ajax 来异步上传图片,这个时候通过 Ajax POST 数据到后台后,却获取不到 req.files.filesName.path 这个属性。下面是我通过同步提交表单成功的代码:

<form method="post" enctype="multipart/form-data" action="/admin/doFile">
	<input type="file" name="filesName">
	<input type="button" value="提交" id="btn">
	<input type="submit" value="OK">
</form>
exports.doFile = function(req, res,next){
// 获得文件的临时路径
var tmp_path = req.files.filesName.path;
var target_path = './public/uploads/' + req.files.filesName.name;
var patharray = target_path.split("/"); 
fs.rename(tmp_path, target_path, function(err) {

    if (err) throw err;
    fs.unlink(tmp_path, function() {

        if (err) throw err;

        var openUrl = '/'+ patharray[patharray.length-2] +'/'+ patharray[patharray.length-1];

        res.json({
            Url : openUrl,
        });
        // res.send(openUrl);
    });
});

}

通过同步 POST 提交上面代码可以正常运行提交图片,但是我通过 Ajax 提交表单,后台且获取不到 req.files.filesName.path 这个属性值,求教各位大神是怎么解决异步提交图片的??


7 回复

要解决异步上传图片的问题,我们需要确保前端和后端都正确处理了文件上传。在使用 expressmulter 处理文件上传时,需要特别注意一些细节。

前端部分

首先,你需要确保你的 AJAX 请求正确地发送了文件数据。你可以使用 FormData 对象来封装文件数据。

<form id="uploadForm">
    <input type="file" name="filesName" id="fileInput">
    <button type="button" id="uploadButton">上传</button>
</form>

<script>
document.getElementById('uploadButton').addEventListener('click', function() {
    var fileInput = document.getElementById('fileInput');
    var file = fileInput.files[0];
    var formData = new FormData();
    formData.append('filesName', file);

    fetch('/admin/doFile', {
        method: 'POST',
        body: formData
    })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
});
</script>

后端部分

在后端,你需要使用 multer 中间件来处理文件上传。确保你正确配置了 multer

const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const app = express();

// 配置 multer
const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, './public/uploads/');
    },
    filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
    }
});

const upload = multer({ storage: storage });

app.post('/admin/doFile', upload.single('filesName'), function(req, res, next) {
    // 获取文件的临时路径
    var tmp_path = req.file.path;
    var target_path = './public/uploads/' + req.file.filename;

    fs.rename(tmp_path, target_path, function(err) {
        if (err) throw err;
        fs.unlink(tmp_path, function() {
            if (err) throw err;
            var openUrl = '/' + path.basename(target_path);
            res.json({
                Url: openUrl
            });
        });
    });
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 前端:使用 FormData 对象将文件添加到请求中,并通过 fetch 发送 AJAX 请求。
  2. 后端:使用 multer 处理文件上传。multer 会自动解析文件并将其存储在指定目录中。你需要配置 multer 的存储策略,以确定文件保存的位置和文件名。
  3. 文件重命名和删除:在成功上传文件后,删除临时文件,并将文件移动到目标位置。最后返回文件的 URL。

这样,你就可以通过 AJAX 异步上传图片,并在后端正确处理文件上传了。


对的,我用的jquery来操作的

怎么用FormData来操作呢?不懂,能具体点吗?

成功了,感谢,我用FormData提交数据成功了

var fd = new FormData();
fd.append('data', 'your data');
xhr.send(fd);

差不多这样?

在使用Ajax进行异步上传图片时,你需要确保前端和后端正确处理了文件上传的过程。通常情况下,Ajax上传文件需要使用FormData对象,并且需要设置适当的请求头。以下是一个示例,展示了如何使用jQuery进行Ajax异步上传图片。

前端代码

<form id="uploadForm">
    <input type="file" name="filesName" id="filesName">
    <button type="button" id="uploadBtn">上传</button>
</form>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
    $('#uploadBtn').click(function() {
        var formData = new FormData($('#uploadForm')[0]);

        $.ajax({
            url: '/admin/doFile',
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function(response) {
                console.log('上传成功', response.Url);
            },
            error: function(error) {
                console.error('上传失败', error);
            }
        });
    });
});
</script>

后端代码

确保你的后端代码能够正确处理文件上传。这里使用multer中间件来处理文件上传:

const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const app = express();
const upload = multer({ dest: 'uploads/' });

app.post('/admin/doFile', upload.single('filesName'), function(req, res, next) {
    try {
        // 获取文件的临时路径
        var tmp_path = req.file.path;
        var target_path = path.join(__dirname, 'public/uploads/', req.file.originalname);

        fs.rename(tmp_path, target_path, function(err) {
            if (err) throw err;
            fs.unlink(tmp_path, function(err) {
                if (err) throw err;

                var openUrl = '/public/uploads/' + req.file.originalname;

                res.json({
                    Url: openUrl,
                });
            });
        });
    } catch (error) {
        next(error);
    }
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 前端:使用FormData对象来包含文件数据,并通过Ajax发送。

    • processData: falsecontentType: false 是必要的,以确保jQuery不会对FormData进行任何处理或设置错误的Content-Type。
  2. 后端:使用multer中间件来处理文件上传。

    • upload.single('filesName') 表示单个文件上传,并将文件保存在uploads/目录下。
    • req.file 包含上传的文件信息,如路径、原始文件名等。

通过以上配置,你可以实现通过Ajax异步上传图片的功能。

回到顶部