关于前后端文件传输问题?

问题描述

我想将前端获取到的文件通过POST请求作为请求体参数传给后端,但是传过去之后发现文件是个空对象{}

问题出现的环境背景及自己尝试过哪些方法

问过chatgpt和查阅的一些资料后我尝试将File对象转化为Blob对象然后再传给后端,结果发现还是空对象{};之后我又尝试通过FormData来作为POST请求体参数可还是无济于事

相关代码

const videoInfo = reactive<videoInfo>({
  videoFile: useVideo().videoFile,
  videoCover: useVideo().videoCover,
  title: "",
  type: "",
  tag: [],
  description: "",
})

function uploadVideo(){
  videoInfo.videoFile = fileToBlob(videoInfo.videoFile)
  videoInfo.videoCover = fileToBlob(videoInfo.videoCover)
  console.log(videoInfo.videoFile)
  upload(videoInfo)

  // videoInfo.videoFile = new FormData()
  // videoInfo.videoCover = new FormData()
  // videoInfo.videoFile.append("file",fileToBlob(useVideo().videoFile))
  // videoInfo.videoCover.append("cover",fileToBlob(useVideo().videoCover))
  // console.log(videoInfo.videoFile.get("file"))
  // upload(videoInfo)
}
export const upload = function(videoInfo){
    return service({
        url: "/uploadVideo",
        method: "POST",
        data:{
            videoFile: videoInfo.videoFile,
            videoCover: videoInfo.videoCover,
            title: videoInfo.title,
            type: videoInfo.type,
            tag: videoInfo.tag.join(","),
            description: videoInfo.description
        },
        headers:{
            isToken: true
        }
    })
}

以下是nodejs后端对路由的统一处理:

import express from "express"
import bodyParser from "body-parser";
import expressSession from "express-session"
import redis from "redis"
import config from "./config/config.js"
import MyError from "./exception/index.js";
import http from "http";
import {FORBIDDEN_ERROR_CODE, NO_AUTH_ERROR_CODE} from "./exception/errorCode.js"
import morgan from "morgan"
import db from "./db.js"
import redisClient from "./redis.js";
import {getToken} from "./utils/token.js";
// import RedisStore from "connect-redis"
// const RedisStore = require("connect-redis")(expressSession);

//连接redis
redisClient.on("connect", function () {
    console.log("Redis client connected");
});
redisClient.on("error", function (e) {
    console.error(e);
});

// 请求大小限制
const requestLimit = "5120kb";

class ExpressServer {
    constructor() {
        this.app = express();
        // 上下文请求路径
        this.contextPath = "/api";
        // 请求日志
        this.app.use(morgan("short"));
        this.app.use(
            bodyParser.urlencoded({ extended: false, limit: requestLimit })
        );
        this.app.use(bodyParser.json({ limit: requestLimit }));
        this.app.set("x-powered-by", false);
        this.app.all("*", (req, res, next) => {
            // 开启跨域
            res.setHeader("Access-Control-Allow-Credentials", "true");
            const origin = req.get("Origin");
            // 允许的地址 http://127.0.0.1:9000 这样的格式
            if (origin) {
                res.setHeader("Access-Control-Allow-Origin", origin);
            }
            // 允许跨域请求的方法
            res.setHeader(
                "Access-Control-Allow-Methods",
                "POST, GET, OPTIONS, DELETE, PUT"
            );
            // 允许跨域请求 header 携带哪些东西
            res.header(
                "Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, If-Modified-Since"
            );
            next();
        });
        // 设置Express的Session存储中间件(跟之前session设置方法一样,只加了store项为redis存储)
        // const sessionOptions = {
        //     // store session存储实例,默认为一个新的 MemoryStore 实例。
        //     store: new RedisStore({ client: redisClient }), // 只需设置这个就可存储到redis
        //     name: "session_id", // 默认connect.sid
        //     secret: "yupi", // 设置签名秘钥  内容可以任意填写
        //     resave: false, // 强制保存,如果session没有被修改也要重新保存,默认true(推荐false)
        //     saveUninitialized: true, // 如果原先没有session那么就设置,否则不设置(推荐true)
        //     rolling: true, // 每次请求更新有效时长
        //     cookie: {
        //         // domain: ".yuindex.com", // 需要共享 cookie 时再设置
        //         // 全局设置 cookie,就是访问随便 api 就会设置 cookie,也可以在登录的路由下单独设置
        //         maxAge: 1000 * 60 * 60 * 24 * 30, // 30 天后过期
        //         httpOnly: true, // 是否允许客户端修改 cookie(默认 true 不能被修改)
        //     },
        // };
        // this.app.use(expressSession(sessionOptions));
        this.server = http.createServer(this.app);
    }

    setRoute(path, method, handlerFunction) {
        const handler = async (req, res) => {
            // IP 过滤
            const requestClientIp = getClientIp(req);
            if (!requestClientIp) {
                return FORBIDDEN_ERROR_CODE;
            }
            const event = req.body;
            let result;
            try {
                const startTime = new Date().getTime();
                let params;
                if (event.file) {
                    let eventCopy = { ...event };
                    eventCopy.file = undefined;
                    params = JSON.stringify(eventCopy);
                } else {
                    params = JSON.stringify(event);
                }
                console.log(
                    `req start path = ${req.path}, clientIp = ${requestClientIp}, params = ${params}`
                );
                if (req.headers.istoken){
                    if (await getToken(req.headers.authorization)){
                        const token = await getToken(req.headers.authorization)
                        event.Authorization = parseInt(token)
                        console.log(typeof event.Authorization)
                    }else {
                        throw MyError(NO_AUTH_ERROR_CODE,"无权限访问,请重新登录")
                    }
                }
                result = await handlerFunction(event, req, res);
                // 封装响应
                result = {
                    code: 200,
                    data: result,
                };
                console.log(
                    `req end path = ${
                        req.path
                    }, clientIp = ${requestClientIp}, params = ${params}, costTime = ${
                        new Date().getTime() - startTime
                    }`
                );
            } catch (e) {
                // 全局异常处理
                if (e instanceof MyError) {
                    result = {
                        code: e.code,
                        message: e.message,
                        data: null,
                    };
                } else {
                    result = {
                        code: 500,
                        data: null,
                        message: "server error",
                    };
                }
                console.error(
                    `req error path = ${
                        req.path
                    }, clientIp = ${requestClientIp}, params = ${JSON.stringify(event)}`,
                    e
                );
            }
            res.send(result);
        };
        if (method === "POST"){
            this.app.post(this.contextPath + path, handler);
        }
        if (method === "GET"){
            this.app.get(this.contextPath + path, handler);
        }
    }

    listen(port) {
        this.server.listen(port);
        let url = `http://localhost:${port}`;
        if (this.contextPath) {
            url += this.contextPath;
        }
        console.log(`server start at ${url}, env = ${process.env.NODE_ENV}`);
    }
}

/**
 * 获取真实客户端 ip
 * @param req
 * @returns {*|string}
 */
function getClientIp(req) {
    if (!req) {
        return "";
    }
    return (
        req.headers["x-forwarded-for"] ||
        req.connection?.remoteAddress ||
        req.socket?.remoteAddress ||
        req.connection?.socket?.remoteAddress ||
        req.ip
    );
}

// module.exports.CloudBaseRunServer = ExpressServer;
export default ExpressServer
阅读 2.5k
2 个回答
export const fileUpload = (params: any): Promise<any> => {
  return request({
    headers: {
      'Content-Type': 'multipart/form-data',
    },
    method: 'post',
    url: '/api-edu-polymeric/file/upload',
    data: params
  });
};
function uploadVideo() {
  const formData = new FormData();
  formData.append('videoFile', useVideo().videoFile);
  formData.append('videoCover', useVideo().videoCover);
  formData.append('title', videoInfo.title);
  formData.append('type', videoInfo.type);
  formData.append('tag', videoInfo.tag.join(','));
  formData.append('description', videoInfo.description);

  return service({
    url: '/uploadVideo',
    method: 'POST',
    data: formData,
    headers: {
      isToken: true,
      'Content-Type': 'multipart/form-data', // 这里要设置Content-Type为multipart/form-data
    },
  });
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题