不吃猫的鱼y 2024-11-01 20:58 采纳率: 82.3%
浏览 4
问题最晚将于11月09日00:00点结题

用户端如何上传图片到服务器和数据库里

vant4+若依后端
注册功能里的上传图片,通过vant的van-uploader组件上传图片,存入到数据库里的是一个blob:http://localhost:8000/9c-4d3b-b22b-987868fe2cd5,实际上这个图片并没有上传到服务器,感觉像是一个缓存,项目重新启动图片就无法显示了,有没有办法正确的上传图片到服务器和数据库,最好和若依上传图片的路径一样,若依图片存放数据库路径如下

img

<template>
  <img style="height: 200px; width: 100%" src="../assets/010.jpg" alt="" />
  <div class="one">注册账号</div>
  <div class="text">
    <van-form @submit="onSubmit" label-align="right">
      <van-cell-group inset>
        <van-field v-model="state.userUsername" name="userUsername" placeholder="请输入用户名" label="用户名:"
          :rules="[{ required: true, message: '用户名不能为空!' }]" />
        <van-field v-model="state.userPassword" name="userPassword" placeholder="请输入密码" type="password" label="密码:"
          :rules="[{ required: true, message: '密码不能为空!' }]" />
        <van-field v-model="state.userpass2" name="userpass2" placeholder="请确认密码" type="password" label="确认密码:"
          :rules="[{ validator, validatorMessage: '请确认密码不能为空!' }]" />
        <van-field v-model="state.userPhone" name="userPhone" placeholder="请输入电话" label="电话号码:"
          :rules="[{ pattern, message: '请输入正确号码' }]" />
        <van-field name="userSex" label="性别:">
          <template #input>
            <van-radio-group v-model="state.userSex" direction="horizontal">
              <van-radio name="男"></van-radio>
              <van-radio name="女"></van-radio>
            </van-radio-group>
          </template>
        </van-field>
        <van-field v-model="state.userNickname" name="userNickname" placeholder="请输入昵称" label="昵称:"
          :rules="[{ required: true, message: '昵称不能为空!' }]" />
        <van-field v-model="state.userName" name="userName" placeholder="请输入姓名" label="姓名:"
          :rules="[{ required: true, message: '姓名不能为空!' }]" />
        <van-field name="userPic" label="头像上传">
          <template #input>
            <van-uploader v-model="state.userPic" :after-read="afterRead" :action="action"  :max-count="1" />
          </template>
        </van-field>
      </van-cell-group>
      <div style="margin: 16px">
        <van-button round block type="primary" style="background-color: #f3a778;border: 0px;" native-type="submit">
          注册
        </van-button>
      </div>
    </van-form>
  </div>
  <van-divider :style="{ color: '#f3a778', borderColor: '#f3a778', padding: '0 16px' }" @click="tologin()">
    已有账号,返回登陆
  </van-divider>
</template>

<script setup>
import { ref } from "vue";
import { RegisterApi } from "@/api";
import { useRouter } from "vue-router";
import { showSuccessToast, showFailToast } from "vant";
import instance from "@/utils/http"
const router = useRouter();
const action = ref(instance.baseURL+ "/profile/upload/user")
//上传图片
const afterRead = (file) => {
  console.log(file)

  console.log(file.file.name);

};

const state = ref({
  userUsername: "",
  userPassword: "",
  userpass2: "",
  userPhone: "",
  userSex: "",
  userNickname: "",
  userName: "",
  userPic: []
});

const validatorMessage = (value) => {
  if (value === "") {
    return "确认密码不能为空!";
  }
  if (value !== state.value.Arrayuserpass) {
    return "两次密码要相同!";
  }
  return;
};

//正则表达式
const pattern = /^1[3-9]\d{9}$/;

const RegisterUser = async (e) => {
  const res = await RegisterApi(e);
  console.log(res.code, 'res.code')
  if (res.code == "200") {
    showSuccessToast("注册成功!");
    router.push("/login");

  } else {
    showFailToast("注册失败!");
  }
};
//返回登录
const tologin = () => {
  router.push("/login");
};
const onSubmit = (e) => {
  RegisterUser(e);
  console.log(e);
  console.log("+++++");
};
</script>

<style scoped>
.one {
  color: #000000;
  display: flex;
  justify-content: left;
  font-size: 30px;
  font-family: "宋体";
  font-weight: bold;
  margin-left: 20px;
}

.van-field_error_message {
  color: aqua !important;
}

.btn {
  width: 300px;
  margin-left: 10%;
  height: 50px;
  background-color: #48e1e3;
  color: white;
  border-radius: 20px;
  border: 0px;
}

.text {
  color: aquamarine;
}
</style>


接口

// 8-插入数据(注册用户)
export const RegisterApi = (events) => {
  events.userPic = events.userPic[0].objectUrl

  return instance({
    url: "/api1/XjnUser/XjnUser",
    data: events,
    method: "POST",
    headers: { "Content-Type": "application/json" },
  });
};

项目端口如下图

img


上传图片时,打印file显示如下

img

  • 写回答

11条回答 默认 最新

  • 问答-莫得感情 2024-11-01 20:59
    关注

    ️题主您好️,目前由我为您解答👇🏼
    🧡参考谷歌智能助手,由吾为汝整理提供🧡

    你遇到的问题是 van-uploader 默认情况下不会自动上传文件到服务器,它只是将文件读取到浏览器内存中,并生成一个临时的 blob: URL。因此,当你重启项目后,这个 URL 就失效了,图片自然也就无法显示了。

    要解决这个问题,你需要在 after-read 事件中手动上传文件到服务器。结合若依的上传机制,可以这样修改你的代码:

    <template>
      <van-uploader
        v-model="state.userPic"
        :after-read="afterRead"
        :max-count="1"
      />
    </template>
    
    <script setup>
    import { ref } from "vue";
    import { RegisterApi } from "@/api";
    import { useRouter } from "vue-router";
    import { showSuccessToast, showFailToast } from "vant";
    import instance from "@/utils/http";
    
    const router = useRouter();
    const state = ref({
      // ... other fields
      userPic: [],
    });
    
    const afterRead = async (file) => {
      // 使用 FormData 上传文件
      const formData = new FormData();
      formData.append('file', file.file); // file.file 获取原始文件对象
    
      try {
        const res = await instance.post("/profile/upload/user", formData, {
          headers: {
            'Content-Type': 'multipart/form-data' // 重要:设置 Content-Type
          }
        });
    
        if (res.data && res.data.code === 200 && res.data.data) { // 根据若依的返回格式调整
          // 上传成功,将服务器返回的图片路径保存到 state.userPic
          state.value.userPic = [
            {
              url: res.data.data.url, // 假设若依返回的数据结构中包含 url 字段
              name: file.file.name
            }
          ]
          console.log("上传成功:", res.data.data.url);
        } else {
          console.error("上传失败:", res.data.msg);
          showFailToast("头像上传失败!");
        }
      } catch (error) {
        console.error("上传出错:", error);
        showFailToast("头像上传出错!");
      }
    };
    
    const RegisterUser = async (e) => {
      // ...其他代码
      e.userPic = e.userPic[0].url; // 注册时提交图片的 URL
      // ...其他代码
    };
    
    // ...其他代码
    </script>
    

    关键修改点:

    1. 移除 action 属性: 我们不再使用 van-uploaderaction 属性,而是在 afterRead 中手动上传。

    2. 使用 FormData: 使用 FormData 对象来构建表单数据,这是上传文件的标准方式。

    3. 设置 Content-Type: 在请求头中设置 Content-Type: multipart/form-data,这是非常重要的,它告诉服务器这是一个文件上传请求。

    4. 手动上传: 在 afterRead 中使用 instance.post 手动上传文件到 /profile/upload/user 接口。

    5. 处理服务器返回: 上传成功后,将服务器返回的图片 URL 保存到 state.userPic 中。 这里假设若依返回的数据结构类似于 {code: 200, msg: 'success', data: {url: '/upload/xxx.jpg'}},你需要根据实际情况调整。

    6. 注册时提交 URL: 在 RegisterUser 函数中,将 state.userPic[0].url 提交到注册接口,而不是 blob: URL。

    后端接口(/profile/upload/user)调整建议:

    确保你的 /profile/upload/user 接口能够正确处理文件上传,并返回上传后的文件 URL。最好与若依自带的文件上传接口保持一致,方便后续管理。 返回格式建议参考上面,包含 code, msgdata 字段,其中 data 包含文件 URL。

    总结:

    通过以上修改,你就可以实现手动上传图片到服务器,并将服务器返回的 URL 保存到数据库中,从而避免 blob: URL 的问题。 记住,van-uploader 只是一个文件选择器和预览组件,真正的上传逻辑需要你自己实现.

    这个方案尽可能与若依的上传路径保持一致,并且利用了 axiospost 方法和 FormData 对象进行文件上传,更加符合现代前端开发的规范。 记得根据你的后端接口实际情况调整代码。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月1日

悬赏问题

  • ¥15 欧拉系统opt目录空间使用100%
  • ¥15 ul做导航栏格式不对怎么改?
  • ¥20 用户端如何上传图片到服务器和数据库里
  • ¥15 现在研究生在烦开题,看了一些文献,但不知道自己要做什么,求指导。
  • ¥30 vivado封装时总是显示缺少一个dcp文件
  • ¥100 pxe uefi启动 tinycore
  • ¥15 我pycharm运行jupyter时出现Jupyter server process exited with code 1,然后打开cmd显示如下
  • ¥15 可否使用carsim-simulink进行四轮独立转向汽车的联合仿真,实现四轮独立转向汽车原地旋转、斜向形式、横移等动作,如果可以的话在carsim中如何进行相应设置
  • ¥15 Caché 2016 在Java环境通过jdbc 执行sql报Parameter list mismatch错误,但是同样的sql使用连接工具可以查询出数据
  • ¥15 疾病的获得与年龄是否有关