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

Laravel+Vue Apollo环境下文件上传失败问题求助

解决Laravel Lighthouse + Vue Apollo 文件上传错误

后端调整

  1. 修正GraphQL Mutation定义
    你的updateDetail同时使用@update自动CRUD指令和自定义Resolver,会导致逻辑冲突。修改Mutation定义,移除@update,改用@field指定自定义Resolver:
extend type Mutation {
    addUser(input: addUserInput! @spread): User @create
    updateUser(input: updateOnlyUserDetailInput! @spread): User @update
    deleteUser(id: ID!): User @delete

    updateDetail(input: UpdateUserDetail! @spread): UserDetail @field(resolver: "App\\GraphQL\\Mutations\\UpdateDetail")
}
  1. 确保Lighthouse启用Multipart支持
    检查config/lighthouse.php中的middleware数组,确认包含Multipart中间件,没有则添加:
'middleware' => [
    // 保留原有中间件
    \Nuwave\Lighthouse\Support\Http\Middleware\MultipartMiddleware::class,
],
  1. 完善Resolver逻辑
    更新Resolver,确保同时保存文件路径到数据库:
<?php

namespace App\GraphQL\Mutations;

use App\Models\UserDetail;

class UpdateDetail
{
    public function __invoke($root, array $args): UserDetail
    {
        $detail = UserDetail::findOrFail($args['id']);
        
        if (isset($args['avatar'])) {
            $path = $args['avatar']->storePublicly('avatars');
            $detail->avatar = $path;
        }
        
        // 更新其他传入字段
        $detail->fill($args);
        $detail->save();
        
        return $detail;
    }
}

前端调整

  1. 安装文件上传依赖
    安装apollo-upload-client以支持GraphQL multipart请求:
npm install apollo-upload-client
  1. 重新配置Apollo Client
    替换默认的HttpLink为UploadLink:
import { createApp } from 'vue'
import { ApolloClient, InMemoryCache } from '@apollo/client/core'
import { createUploadLink } from 'apollo-upload-client'
import { DefaultApolloClient } from '@vue/apollo-composable'

const uploadLink = createUploadLink({
  uri: '/graphql', // 你的GraphQL接口地址
})

const apolloClient = new ApolloClient({
  link: uploadLink,
  cache: new InMemoryCache(),
})

const app = createApp(App)
app.provide(DefaultApolloClient, apolloClient)
app.mount('#app')
  1. 组件中正确处理文件上传
    在Vue组件中直接传入File对象,而非文件路径:
<template>
  <div>
    <input type="file" @change="handleFileSelect" accept="image/*" />
    <button @click="submitUpdate" :disabled="!selectedFile">更新头像</button>
  </div>
</template>

<script setup>
import { useMutation } from '@vue/apollo-composable'
import gql from 'graphql-tag'

const UPDATE_DETAIL = gql`
  mutation UpdateDetail($input: UpdateUserDetail!) {
    updateDetail(input: $input) {
      id
      avatar
    }
  }
`

let selectedFile = null

const handleFileSelect = (e) => {
  selectedFile = e.target.files[0]
}

const { mutate } = useMutation(UPDATE_DETAIL)

const submitUpdate = async () => {
  try {
    await mutate({
      variables: {
        input: {
          id: '你的用户详情ID', // 替换为实际ID
          avatar: selectedFile
        }
      }
    })
    alert('头像更新成功')
  } catch (err) {
    console.error('上传失败', err)
  }
}
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:15:34