如何在Vuejs和Expressjs中上传文件

3

嘿,请注意,我是Vuejs和Express的新手...所以我正在练习。

我正在尝试使用Vuejs和ExpressJs创建带有图像的用户配置文件,但没有任何文件或文本被上传。

这是我的CreateProfile.vue文件。

       <div class="icon-pic">
       <label for="Password">Upload your Logo / Picture</label>
        <input type="file" ref="file" @change="handleFileUpload"/>
      </div>

      <b-input-group class="mb-2">
        <b-form-input
          id="input-small"
          type="text"
          placeholder="Enter your Name"
          required
          :rules="[rules.required]"
          v-model="profile.fullname"
        ></b-form-input>

        <b-form-input
          id="input-small"
          type="text"
          placeholder="Enter your BrandName"
          v-model="profile.brandname"
        ></b-form-input>
      </b-input-group>

注意:还有其他输入方式,这里只展示了表单的脚本函数。

以下是我的表单脚本函数:

<script>
import ProfileService from '@/services/ProfileService'

export default {
data () {
return {
  profile: {
    fullname: null,
    brandname: null,
    skill1: null,
    skill2: null,
    skill3: null,
    skill4: null,
    socail_handle1: null,
    socail_handle2: null
  },
  file: null,
  error: null,
  rules: {
    required: (value) => !!value || 'Required.'
  }
}},
methods: {
handleFileUpload () {
  const file = this.$refs.file.files[0]
  this.file = file
},
async create () {
  this.error = null
  const formData = new FormData()
  formData.append('file', this.files)
  const areAllFieldsFilledIn = Object.keys(this.profile).every(
    (key) => !!this.profile[key]
  )
  if (!areAllFieldsFilledIn) {
    this.error = 'Please fill in all the required fields.'
    return
  }
  try {
    await ProfileService.post(this.profile, formData)
    this.$router.push({
      name: 'profile'
    })
  } catch (error) {
    this.error = error.response.data.error
  }
}}}

以下是我的 ProfileController.js 文件。
const {Profile} = require ('../models')
const multer = require ('multer')

const fileFilter = (req, file, cb) => {
const allowedTypes = ["image/jpeg", "image/jpg", "image/png"]
if (!allowedTypes.includes(file.mimetype)){
const err = new Error('Incorrect File');
return cb(err, false)
}
cb(null, true)
}

const upload = multer ({
dest: '../public',
fileFilter,
})

module.exports = {
async post (req, res){
    try {
        upload.single('files')
        const profile = await new Profile({
        profile: this.profile,
        files: req.file
      });
      profile.save().then(result => {
        console.log(result);
        res.status(201).json({
          message: "Done upload!"
        })
      })
    } catch (err) {
        console.log(err)
        res.status(500).send({
        error: 'An Error has occured trying to fetch'
    })}}

根据我的 Model/Profile.js 文件

module.exports = (sequelize, DataTypes) => {
const Profile = sequelize.define('Profile', {
     files: {
      type: DataTypes.JSON
     },
     fullname: {
       type: DataTypes.STRING,
       allowNull: false
     },
     brandname: DataTypes.STRING,
     skill1: DataTypes.STRING,
     skill2: DataTypes.STRING,
     skill3: DataTypes.STRING,
     skill4: DataTypes.STRING,
     socail_handle1: DataTypes.STRING,
     socail_handle2: DataTypes.STRING
 })
 return Profile 
 }

请帮我解决这个问题!!!

这是我的route.js文件

const AuthController = require('./controllers/AuthController')
const AuthControllerPolicy = require('./policies/AuthControllerPolicy')
const ProfileControler = require('./controllers/ProfileController')
const upload = require ('multer')

module.exports = (app) => {
app.post('/register',
    AuthControllerPolicy.register,
    AuthController.register)

app.post('/login',
    AuthController.login)

app.get('/profile',
    ProfileControler.index)
    
app.post('/upload', upload.single('file'),
    ProfileControler.upload)

}


也许可以尝试使用Uppy with Vue.js - 我知道这不是一个正式的答案,它取决于您的要求是否需要创建自己的上传器,或者您只是想在Vue中进行简单的文件上传。我与他们没有任何关联,这并不是一个正式的答案,但我过去曾使用过Uppy,它似乎使这些事情变得更容易一些。 - Johan Jarvi
会去查看一下。 - Hemmyhtec Creatives
1个回答

2

我注意到两件事情:

  1. 您没有将multer用作中间件函数

upload.single('file')返回一个函数,应该将其作为中间件在Express路由中传递。您可以在route.js中像这样使用它:

const multer = require('multer');

const upload = multer({
  dest: '../public',
  fileFilter,
});

app.post('/upload', upload.single('file'), ProfileController.post);

然后您可以在post函数中删除上传代码:
module.exports.post = async (req, res) => {
  // Multer makes your file available at req.file
  const file = req.file;

  try {
    // Don't need to await when creating a new Mongo object
    const profile = new Profile({
      profile: this.profile,
      files: file
    });

    // Refactored this to use async/await instead of promises.
    // Avoid mixing promises with async/await.
    const result = await profile.save();
    return res.status(201).json({ message: "Done upload!" });
  } catch (error) {
    console.log(error)
    return res.status(500).send({ error: 'An Error has occured trying to fetch' });
  }
}
  1. 传递给multer的文件输入名称与前端不匹配

您正在配置multer以查找名为files的文件输入:upload.single('files'),但在前端中,您将其命名为file(单数):formData.append('file', this.files)。通常,multer会抛出意外字段错误。请确保这两个完全匹配。

这份免费指南解析Node.js请求将帮助您处理Node.js中的文件上传。


非常感谢,我会尝试的。 - Hemmyhtec Creatives
@maximOrlov,自从我在我的路由中添加了upload.single('file')后,我的上传方法应该是什么样子的呢? upload.single('files') const profile = await new Profile({profile: this.profile, files: req.file 请帮忙看一下!!! - Hemmyhtec Creatives
如果您发布您的路由文件(其中导入了ProfileController.js),我可以调整我的回答以适应您的问题。 - Maxim Orlov
我已经编辑了我的答案,包括新的“post”方法。更改您的路由器以使用ProfileController.post而不是ProfileController.upload,因为您正在导出的方法名为post。我还稍微重构了post方法,请阅读注释。 - Maxim Orlov
让我们在聊天中继续这个讨论 - Hemmyhtec Creatives
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接