流浪的菜袅 2023-02-27 11:38 采纳率: 79.5%
浏览 35
已结题

去掉form表单传图片报错

大家好,小菜袅又来了
是这样的,我一开始上传图片,用form表单提交很顺利,但是这样的话,前端接收不到服务器响应,虽然在submit事件内加上xhr请求可以看到响应,但是这样的话,又会有两次请求。
因为要弄拖拽上传图片,这样的话不是用户触发input:file去选择文件,而且也不想用form表单去提交了,我就去掉form表单,直接btn事件内用xhr去发请求:

 <input type="file" name="avatar" id="">
    <div class="all"></div>
    <button id="btn">上传</button>
<script>
        /*
            drop 在可放置区域放置元素时触发
            dragover 当可拖动元素放置到可放置区域时触发
            dragstart 当可拖动元素开始拖动时触发
            dragenter 拖动的元素进入到可放置区域时触发
            dragleave 拖动的元素离开可放置区域时触发
            dragend 拖放过程结束
        */ 
       const container = document.querySelector('.all')
       const btn = document.querySelector('#btn')
       let file;
       container.addEventListener('dragenter',function(ev) {
            ev.preventDefault()
            ev.target.style.borderColor = 'red'
       })
       container.addEventListener('dragover',function(ev) {
        ev.preventDefault()
       })
       container.addEventListener('drop',function(ev) {
            console.log(111);
            ev.preventDefault()
            const items = Array.prototype.slice.call(ev.dataTransfer.items)
            console.log(items);
            items.forEach(val => {
                console.log(val);
                if(val.kind === 'file') {
                    // getAsFile就是将拖过来的图片,得到图片的file数据
                    file = val.getAsFile()
                    console.log('1111',file);
                    // console.log('file',ev.dataTransfer.files[0]);
                }
            })
       })
       btn.addEventListener('click',function(){
            let formdata = new FormData()
            formdata.append('avatar',file)
            const xml = new XMLHttpRequest()
            xml.open('post','http://localhost:3000/api/swiper',true)
            xml.setRequestHeader("Content-type", "multipart/form-data; boundary=---------------------------" + Date.now().toString(16));
            xml.onlonreadystatechangeoad = function(){
                if (xhr.readyState === 4 && xhr.status === 200) {
                    console.log(xhr.responseText);
                }
            }
            xml.send(formdata)
       })
    </script>

nodejs:

const express = require('express')
const router = express.Router()
const multer = require('multer')
const mysql = require('../model/orm')
let date = new Date()
const moment = require('moment')
let time = date.getTime()
let originalname;
let random = Math.floor(Math.random() * (1000 - 100 + 1)) + 100
let urlStr; 
let obj;
let arr = [];
let storage = multer.diskStorage({
    destination: function(req, file, cb) {
        cb(null, 'public/upload'); 
    },
    filename: function(req, file, cb) {
        originalname = Buffer.from(file.originalname, "latin1").toString("utf8");
        urlStr = time + '-' + random + '-' + originalname
        time = date.getTime()
        random = Math.floor(Math.random() * (10000 - 100 + 1)) + 100
        obj = {
            swi_url:'http://localhost:3000/upload/' + urlStr,
            swi_qiyong:'false',
            swi_type:"活动",
            swi_time:moment(new Date()).format()
        }
        arr.push(obj)
        cb(null, urlStr)
    }
})
let upload = multer({ storage: storage });
// upload.single('form'),
router.post('/',upload.single('avatar'),(req,res) => {
    try {
        console.log('files',req.files);
        console.log('body',req.body);
    } catch (err) {
        console.log(err);
        res.status(500).send(err);
    }
    // console.log(arr);
    // let swiper = mysql.model('swiper')
    // swiper.insert(arr,(err,data) => {
    //     if(err) {
    //         console.log(err);
    //         return 
    //     }
    //     res.send({
    //         code:200,
    //         msg:"post请求处理完毕"
    //     })
    // })
})
module.exports = router

这样子后,前端报500错误,服务器报:表单意外终结(Error: Unexpected end of form),为什么呀,求解答求解答求解答

  • 写回答

2条回答 默认 最新

  • CodeBytes 2023-02-27 11:57
    关注

    该回答引用ChatGPT

    这个错误通常意味着表单格式不正确或丢失了某些必要的表单字段或标记。在你的代码中,我注意到你在发送 XMLHttpRequest 请求时设置了请求头部 Content-type 为 multipart/form-data,这是正确的设置,但是你使用了一个随机分隔符来生成表单边界标识符,这可能会导致表单格式不正确。

    相反,你可以使用 FormData 对象来构建表单数据,FormData 会自动为你生成边界标识符,你可以像这样修改你的前端代码:

    
    btn.addEventListener('click',function(){
      let formdata = new FormData();
      formdata.append('avatar',file);
      const xml = new XMLHttpRequest();
      xml.open('post','http://localhost:3000/api/swiper',true);
      xml.onlonreadystatechangeoad = function(){
          if (xhr.readyState === 4 && xhr.status === 200) {
              console.log(xhr.responseText);
          }
      };
      xml.send(formdata);
    });
    
    

    在你的后端代码中,你使用了 Multer 中间件来处理文件上传。注意,upload.single() 方法只会处理一个文件,并将其存储在 req.file 中。因此,你可以使用 req.file 来获取上传的文件,而不是使用 req.files。此外,如果出现错误,Multer 会将错误存储在 MulterError 对象中,你可以使用 instanceof 操作符来检查是否存在此类错误。在你的代码中,你可以像这样修改后端代码:

    
    router.post('/', upload.single('avatar'), (req, res) => {
      try {
        console.log('file', req.file);
        console.log('body', req.body);
      } catch (err) {
        if (err instanceof multer.MulterError) {
          console.log(err.code);
        } else {
          console.log(err);
        }
        res.status(500).send(err);
      }
    });
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月7日
  • 已采纳回答 2月27日
  • 创建了问题 2月27日

悬赏问题

  • ¥15 用vmmare虚拟机用sentaurus仿真的时候,调用terminal程序,输入swb指令弹出这个,打不开workbench,桌面上面的sentaurus workbench也打不开
  • ¥75 使用winspool.drv的SetPrinter设置打印机失败
  • ¥15 simulink 硬件在环路仿真
  • ¥15 python动态规划:N根火柴摆出的最大数字
  • ¥20 (标签-excel)
  • ¥200 求idea10和MyEclipse7.1
  • ¥20 vb6.0截取当前窗体保存为jpg文件
  • ¥20 苹果手机不使用大疆sdk怎么获取遥控器控制信息或如何接入大疆sdk并且成功上架sdk
  • ¥20 woocommerce 注册按键重定向
  • ¥100 求书法图像文字切割代码