formData手动上传问题前端如何传递后端如何接收


一. 前言

参考文章:
解决Current request is not a multipart request
axios上传文件错误:Current request is not a multipart reques


二. 问题描述

之前使用el-upload使用默认action表单提交.前端默认content-type为multipart/form-data.没有问题. 后期渐进式优化.修改为axios+formdata传递内容.

Current request is not a multipart request
这个错误是因为后端读取MultipartFile 类型数据时,对申请头的类型进行了一个判断,他只识别 multipart 开头的 Content-Type。所以我们需要修改headers 的 Content-Type。但是手动添加headers会产生第二个错误。所以建议使用formdata 的方式.
参数为formdata 时,浏览器会自动添加一个标准的headers。
在这里插入图片描述
在这里插入图片描述
上传代码
在这里插入图片描述

提交post封装请求
在这里插入图片描述

三.前端正确解决方式

前端上传文件总共有两种方式.通过axios-formData和axios传递.
axios可以通过序列化纯字符串传递.但是缺乏这样的经验.后端接收比较麻烦.因此推荐axios-formData

          <el-form-item label="上传简历">
            <el-upload
                ref="recruitRef"
                class="upload-demo"
                drag
                action="#"
                :auto-upload="false"
                :on-change="handleChange"
                limit="1"
            >
              <el-icon class="el-icon--upload">
                <upload-filled/>
              </el-icon>
              <div class="el-upload__text">
                拖拽 或 <em>点击上传</em>
              </div>
              <template #tip>
                <div class="el-upload__tip">
                  .pdf 文件大小 ≤ 500kb
                </div>
              </template>
            </el-upload>
          </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="postResumeForm()">投递</el-button>
      </el-form-item>
const resumeForm = reactive({
  name: '',
  phone: '',
  email: '',
  experience: '',
  education: '',
  position: router.currentRoute.value.params.position
})

const recruitRef = ref()

let formData = new FormData()

function handleChange(uploadFile, uploadFiles) {
  if (!verifyBeforeUpload(uploadFile)) {
    removeFile()
    return
  }
  formData.append("file", uploadFile)
}

function removeFile() {
  if (recruitRef.value) {
    formData = new FormData()
    recruitRef.value.clearFiles()
  }
}

export const ACCEPTED_EXTENSIONS = ['pdf'];

// 单文件大小校验
function verifyFileSize(file) {
    if (file) {
        let fileSize = file.size;
        let fileMaxSize = 1024 * 500;//500kb
        if (fileSize > fileMaxSize) {
            ElMessage.error("文件不能大于500kb!");
            file.value = "";
            return false;
        } else if (fileSize <= 0) {
            ElMessage.error("文件不能为0kb!");
            file.value = "";
            return false;
        }
        return true
    }
    ElMessage.error("必须传递文件!")
    return false;

}

// 校验文件格式和大小
export function verifyBeforeUpload(file) {
    // 格式
    const extension = file.name.split('.').pop().toLowerCase();
    console.log(extension)
    if (!ACCEPTED_EXTENSIONS.includes(extension)) {
        ElMessage.error('仅支持 pdf 格式的文件');
        return false;
    }
    // 大小
    return verifyFileSize(file);
}


function postResumeForm() {
  ElMessageBox.confirm('确认提交?提交后仅能修改一次', '提示', {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(async () => {
    if (formData === null || formData === undefined) {
      ElMessage.info("必须递交简历信息!")
      return
    }
    for (let key in resumeForm) {
      formData.append(key,resumeForm[key])
    }
    let res = await reqPostResumeForm(formData)
    if (res.code !== 200) {
      ElMessage.error("简历投递失败")
      return
    }
    await ElMessageBox.alert("简历投递成功! 3-7个工作日内,您将收到回复", '提示', {
      confirmButtonText: "确认"
    })
    removeFile()
  }).catch((err) => {
    console.log(err)
    ElMessage.info("简历投递已取消!")
  })
}

export function postFiles(url,data={}){
    return axios({
        method: "POST",
        url: 'http://127.0.0.1:8080'+url,
        transformRequest: [function(data, headers) {
            // 去除post请求默认的Content-Type
            delete headers['Content-Type']
            return data
        }],
        data: data,
    })
}

在这里插入图片描述
在这里插入图片描述


四. 后端接收代码

 @PostMapping("/uploadBatchTaxRevenue")
    public ResponseResult uploadBatchTaxRevenu(@RequestParam("file") MultipartFile[] files) throws IOException {
        if (files.length == 0) {
            return ResponseResult.okResult(403, "上传文件不能为空!");
        }
        for (MultipartFile file : files) {
            System.out.println(file.getName());
            EasyExcel.read(file.getInputStream(), TaxRevenue.class, new TaxRevenueDataListener(taxRevenueService))
                    .sheet()
                    .doRead();
        }
        return ResponseResult.okResult(200, "上传成功");
    }

在这里插入图片描述

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 前端通过formdata的方式上传文件,可以使用表单文件控件或者通过js代码创建formdata对象进行上传。对于表单控件上传,需要在form标签中设置enctype属性为multipart/form-data,然后在input标签中设置type属性为file,这样即可将文件存储在formdata对象中。如果通过js代码创建formdata对象,直接通过append方法将文件添加到对象中,如下所示: ``` let formData = new FormData(); formData.append('file', file); ``` 其中,file为需要上传的文件对象。 后端使用koa-body中间件可以方便地处理上传的文件。先要在koa应用中使用该中间件,然后通过ctx.request.files获取上传的文件,如下所示: ``` const Koa = require('koa'); const koaBody = require('koa-body'); const app = new Koa(); app.use(koaBody({ multipart: true, // 支持文件上传 formidable: { maxFileSize: 200*1024*1024, // 设置上传文件大小,默认2M } })); app.use(async (ctx) => { const file = ctx.request.files.file; console.log(file.name, file.size); // 打印上传的文件名和大小 ctx.body = '上传成功'; }) ``` 其中,multipart设置为true表示支持文件上传formidable对象中的maxFileSize表示最大上传文件大小,默认为2M。在处理上传的文件时,获取文件对象通过ctx.request.files即可,可以获取文件名、类型、大小等信息。最后,需要设置返回的数据为上传成功即可。 ### 回答2: 前端在实现文件上传的过程中,需要使用到formdata对象,formdata对象可以支持上传文件、文本信息以及表单数据等。要进行文件上传,需要注意选择文件类型的input的属性设置为"file",然后通过formdata对象将文件添加到数据中,在使用Ajax等技术将数据发送给后端。在使用formdata上传文件时,需要注意不同浏览器之间formdata对象的兼容性,可以使用polyfill等技术来进行统一。 对于后端的Koa框架来说,接收上传的文件可以使用koa-body中间件。koa-body中间件可以接收文件、文本信息以及表单数据等,可以将上传文件保存在指定的路径下,并且将上传的文件信息添加到ctx.request.body中进行统一管理。在使用koa-body中间件时,需要注意对于文件大小、上传路径、文件格式等进行配置管理,以免出现上传失败或者数据丢失的情况。 除此之外,如何管理和处理上传的文件也是需要考虑的重点,可以考虑使用nodejs中的fs模块进行文件操作,或者使用第三方插件如multer等来进行统一管理。在处理上传的文件时,还要注意对于文件大小、路径、格式进行校验和处理,以确保数据的有效性和安全性。 ### 回答3: 前端使用Formdata上传文件,示例如下: ``` const formData = new FormData() formData.append('file', file) axios.post('/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then((res) => { console.log(res.data) }) ``` 后端使用koa-body来接收上传的文件,示例如下: ``` const Koa = require('koa') const koaBody = require('koa-body') const app = new Koa() app.use(koaBody({ multipart: true, formidable: { uploadDir: './uploads', // 上传文件保存的路径 keepExtensions: true, // 保留文件扩展名 maxFieldsSize: 2 * 1024 * 1024 // 最大文件大小为2MB } })) app.use(async (ctx) => { const file = ctx.request.files.file console.log(file) // 处理文件逻辑 }) app.listen(3000) ``` 其中,koa-body需要设置multipart为true,表示支持文件上传formidable则可以设置一些参数,如uploadDir表示文件保存的路径,keepExtensions表示是否保留文件扩展名,maxFieldsSize表示最大文件大小,可以根据需要进行调整。在处理请求时,可以通过ctx.request.files.file获取上传的文件信息,然后进行相应的业务逻辑处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

最难不过坚持丶渊洁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值