如何使用 Nuxt 3 服务器作为带有 FormData 的直通 API 来隐藏外部端点

问题描述 投票:0回答:3

我正在尝试了解 Nuxt /server API,但似乎无法弄清楚如何将带有表单数据(即文件)的 POST 请求发送到 Nuxt 服务器以转发到外部服务:

在我的

pages.vue
文件中我有这个方法:

async function onSubmit() {
  const formData = new FormData();
  for (let file of form.files) {
    await formData.append("image", file);
  }

  await $fetch("/api/send", {
    method: "POST",
    body: formData
  });
}

然后在

/server/api/send.js
我有:

export default defineEventHandler(async (event) => {
  const { method } = event.node.req;

// I THINK THE ISSUE IS HERE 
  const body =
    method !== "GET" && method !== "HEAD"
      ? await readMultipartFormData(event)
      : undefined;

  const response = await $fetch.raw(https://*******, {
      method,
      baseURL: *********,
      headers: {
      },
      body: body
    });

   return response._data;
}

我正在使用 Nuxt 有效地创建一个直通 API,以便外部端点不会暴露给最终用户。只是无法弄清楚如何以正确的格式访问 formData 以在服务器端传递。我认为我不应该使用

readMultipartFormData()
,因为这似乎以某种方式解析数据,而我只想将 formData 直接传递到外部 API。有什么建议吗?

我尝试过同时使用

readMultipartFormData()
readBody()
,但似乎都不起作用。我实际上不需要阅读正文,而是获取它并在没有任何格式的情况下传递它......

vue.js nuxt.js
3个回答
1
投票

我在这个问题上挣扎了很多,没有干净的方法,每次我必须使用 Nuxt 3 处理文件上传时,我只是使用 nuxt-proxy 前端绕过服务器,这也很难看......

  proxy: {
    options: {
      target: 'https://my-backend.herokuapp.com',
      changeOrigin: true,
      pathRewrite: {
        '^/api/mediaupload/': '/api/mediaupload/',
      },
      pathFilter: [
        '/api/mediaupload/',
      ]
    }
  },

在我的页面中:

    const addFiles = (e: { target: { files: any; }; }): void => {
      console.log('e',e)
      const formData = new FormData();
      for (let i = 0; i < e.target.files.length; i++) {
        formData.append("file"+i, e.target.files[i]);
      }
      formData.append("foo", bar);
      refInput = formData
    };

提交按钮:

const submitFiles = async () => {
  domError.value = null
  const token = useStatefulCookie('token')
  if (token.value && refInput) {
    const authorization = `Bearer ${token.value.access_token}`
    const data = await $fetch("/api/mediaupload/", {
      method: "POST",
      body: refInput,
      headers: {
        // 'Content-Type': 'multipart/form-data', <- finally useless
        'Authorization': authorization,
      },
      async onResponseError({ request, response, options }) {
        domError.value = response._data
      }
    })
  }
  else return
}

0
投票

如果您想将带有 formdata 的数据传递到端点,请尝试此库: https://www.npmjs.com/package/object-to-formdata

代码:

import { serialize } from 'object-to-formdata';
const formData = serialize(body);
const response = await $fetch.raw(https://*******, {
      method,
      baseURL: *********,
      headers: {
      },
      body: formData
    });

0
投票

我设法让它与丑陋的解决方案一起工作,首先你必须将 nuxt 更新到版本 3.2.0 分钟,然后这是我的正面

let jobApplicationDTO = {
            firstName: values.firstName,
            lastName: values.lastName,
            email: values.email,
            phoneNumber: values.phoneNumber,
            company: values.company,
            shortDescription: values.shortDescription
        };

        const formData = new FormData();
        formData.append("application", new Blob([JSON.stringify(jobApplicationDTO)], {type: "application/json"}));
        formData.append("file", values.file) ;

        //formData.append("file", values.file );
        await useFetch("/api/application", {
            method: "POST",
            body: formData,
            onResponse({request, response, options}) {
                // Process the response data
                if (response.status === 200) {
                    errorMessage.value = "";
                    successMessage.value = "Your application wa sent successfully, you will be contacted soon !";
                }
            },
            onResponseError({request, response, options}) {
                console.debug(response);
                if (response.status === 400) {
                    successMessage.value = "";
                    errorMessage.value = "There may be an issue with our server. Please try again later, or send an email to [email protected]";
                } else {
                    successMessage.value = "";
                    errorMessage.value = "Sorry we couldn’t send the message, there may be an issue with our server. Please try again later, or send an email to [email protected]";
                }
            },
        });
    }

和服务器端

import {FormData} from "node-fetch-native";

export default defineEventHandler(async (event) => {
    const {BACKEND_REST_API, ENQUIRY_TOKEN} = useRuntimeConfig();       
//retrieve frontend post formData
const form = await readMultipartFormData(event);
    const applicationUrl = BACKEND_REST_API + '/job/apply'
    console.log("url used for enquiry rest call :" + applicationUrl);
    console.log("Job application token :" + ENQUIRY_TOKEN);
    
    const formData = new FormData();

    console.log(form);


    if (form) {
        formData.append(form[0].name, new Blob([JSON.stringify(JSON.parse(form[0].data))], {type:  form[0].type}));
        formData.append(form[1].name, new Blob([form[1].data], {type: form[1].type}), form[1].filename);
    }

    console.log(formData.values);

    return await $fetch(applicationUrl, {
        method: "POST",
        body: formData,
        headers: {
            Authorization: ENQUIRY_TOKEN,
        },
    });
})

有趣的是在前端你必须创建一个 formData ,然后获取内容并从之前在 MultiFormPart[] 中转换的 formData 重新创建一个 formData ,我在 nuxt 上创建了一个票证以了解如何正确执行此操作

© www.soinside.com 2019 - 2024. All rights reserved.