You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Cloudinary原生JS上传代码适配至Remix框架?

在Remix中实现Cloudinary图片上传(适配原Vanilla JS示例)

1. 整合表单结构到Remix组件

先把原示例的HTML表单改造为Remix的Form组件,注意添加encType="multipart/form-data",同时加入Cloudinary上传所需的隐藏字段(需提前在Cloudinary后台配置未签名上传预设):

import { useState } from "react";
import { Form } from "@remix-run/react";

export default function PostForm() {
  const [previewUrl, setPreviewUrl] = useState(null);
  const [uploadStatus, setUploadStatus] = useState("");

  // 处理文件选择与Cloudinary上传
  const handleFileSelect = async (e) => {
    const file = e.target.files[0];
    if (!file) return;

    // 生成本地预览图
    const preview = URL.createObjectURL(file);
    setPreviewUrl(preview);

    // 组装Cloudinary上传表单数据
    const formData = new FormData();
    formData.append("file", file);
    formData.append("upload_preset", "你的上传预设名称");

    try {
      setUploadStatus("上传中...");
      const response = await fetch("https://api.cloudinary.com/v1_1/你的Cloudinary云名称/image/upload", {
        method: "POST",
        body: formData,
      });

      const data = await response.json();
      if (data.secure_url) {
        // 将Cloudinary返回的图片URL存入隐藏字段,提交表单时同步发送
        document.getElementById("cloudinary-image-url").value = data.secure_url;
        setUploadStatus("上传成功");
      }
    } catch (err) {
      setUploadStatus("上传失败,请重试");
      console.error(err);
    }
  };

  return (
    <Form method="post" encType="multipart/form-data">
      {/* 原有创建Post的字段 */}
      <input type="text" name="title" placeholder="Post标题" required />
      
      {/* 图片选择控件 */}
      <input 
        type="file" 
        name="image" 
        accept="image/*" 
        onChange={handleFileSelect}
      />
      
      {/* 存储Cloudinary返回的图片URL,用于表单提交 */}
      <input 
        type="hidden" 
        id="cloudinary-image-url" 
        name="imageUrl" 
      />
      
      {/* 预览图与上传状态提示 */}
      {previewUrl && <img src={previewUrl} alt="图片预览" style={{width: "200px", marginTop: "10px"}} />}
      <p>{uploadStatus}</p>
      
      <button type="submit" disabled={uploadStatus === "上传中..."}>创建Post</button>
    </Form>
  );
}

2. Remix后端处理表单提交

在表单对应的路由文件中,编写action函数处理POST请求,获取Post数据与图片URL后完成创建逻辑:

import { ActionFunctionArgs, json } from "@remix-run/node";

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const title = formData.get("title") as string;
  const imageUrl = formData.get("imageUrl") as string;

  // 替换为你的实际创建Post逻辑(比如存入数据库)
  // await createPost({ title, imageUrl });

  return json({ success: true, post: { title, imageUrl } });
}

关键注意事项

  • 务必在Cloudinary后台创建未签名上传预设,否则前端无法直接上传
  • 替换代码中的你的Cloudinary云名称和你的上传预设名称为实际配置值
  • 若需要更高安全性,可将上传逻辑移至Remix后端(后端签名后调用Cloudinary API),前端仅负责传递文件到后端

内容的提问来源于stack exchange,提问作者Nuno Marques

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:30:54