使用 Laravel 后端的 Vue-resource + FormData 文件上传

Vue-resource + FormData File Upload with Laravel Backend

我已经在 VueJS 论坛上提出了我的问题:https://forum.vuejs.org/t/file-upload-with-formdata-vue-resource/20952/3

但是!为了重复我的成功机会,我会问你我的问题。

只是我有一个输入类型文件(没有表单父节点),我正在尝试将一个带有 FormData 和 Vue-resource http 的文件异步上传到我的 Laravel 5.5 API 后端..

为了测试我的上传,我的控制器 return 一个 JSON 响应转储了我的 $request。

好吧,我有一个 200 代码,但不幸的是我的回复是空的..

感谢您的帮助:)

Request payload here

客户代码

export default {
  name: 'profile',
  data () {
    return {
      user: {},
      files: [],
      filepath: false,
      imageData: ''
    }
  },
  mounted () {
    this.user = this.$store.getters.user
  },
  methods: {
    reset: function () {
      this.remove()
    },
    upload: function (e) {
      var data = new FormData()
      var file = this.files[0]

      data.append('test', 1234)
      data.append('avatar', file)

      this.$http({
        url: this.user.actions.updateAvatar,
        body: data,
        method: 'POST',
        responseType: 'json',
        before: function (request) {
          console.log(request)
        }
      })
      .then((response) => {
        console.log(response)
      })
      .catch((errorResponse) => {
        console.log(errorResponse)
      })
    },
    sync: function (e) {
      e.preventDefault()
      this.files = e.target.files || e.dataTransfer.files
      if (!this.files.length) {
        return
      }
      this.createFile(e, this.files[0])
    },
    createFile: function (e, file) {
      this.filepath = URL.createObjectURL(file)
    },
    remove: function () {
      URL.revokeObjectURL(this.filepath)
      this.filepath = false
      this.files = []
      document.getElementById('avatar').value = ''
    }
  }
}
<template>
    <!-- header profile -->
    <div id="profile">
        <section class="container">
            <div class="row">
                <div class="col-lg-8 col-lg-offset-2">
                    <div class="profile">
                        <input type="hidden" name="_method" value="PUT"/>
                        <header>
                            <label for="avatar" class="avatar" v-if="!filepath">
                            <img :src="user.avatar || 'http://placehold.it/50x50'" alt="avatar">
                            </label>
                            <div class="avatar" @click="reset" v-if="filepath">
                                <img :src="filepath" alt="avatar">
                            </div>
                            
<!-- Trigger a preview -->
<input @change="sync" id="avatar" name="avatar" type="file" accept="image/*;" class="hide">
                            
                            <div class="info">
                                <span class="name">John Snow 
                                    <router-link :to="{ name: 'UserSettings' }">
                                        <span class="ico gear"></span>
                                    </router-link>
                                </span>
                                <span class="desc">Une bio de 40 caractères</span>
                                <span class="social">
                                    <span class="ico fb"></span>
                                    <span class="ico tw"></span>
                                </span>
                            </div>
                        </header>
<!-- Trigger upload -->                     
<span @click="upload" class="btn-save" v-if="filepath">
    Enregistrer
</span>
                    </div>
                </div>
                <div class="col-lg-8 col-lg-offset-2">
                    <div class="col-lg-12">
                        <router-link :to="{ name: 'UserPosts' }">
                            <span for="dechet" class="nb-dechet">122 déchêts postés</span>
                        </router-link>
                        |
                        <router-link :to="{ name: 'UserBookmarks' }">
                            <span for="dechet" class="nb-dechet">122 déchêts sauvegardés</span>
                        </router-link>
                        |
                        <router-link :to="{ name: 'UserTrophies' }">
                            <span for="reward" class="nb-dechet">1 trophé obtenu</span> 
                        </router-link>
                    </div>
                </div>
            </div>
        </section>    
        <hr>
        <!-- posts -->
        <section class="container">
            <div class="row">
                <router-view></router-view>
            </div>
        </section>
    </div>
</template>

服务器端代码

Route | Dummy Controller

您的代码没有任何问题,只是 response()->json() 无法将 Illuminate\Http\UploadedFile 转换为 json。

您的文件正在上传中,请尝试查看

return response()->json([
   'avatar' => $request->file('avatar')->getClientOriginalName()
]);

您将在响应中得到文件的名称。

原因 无法将 Illuminate\Http\UploadedFile 转换为 JSON 响应的原因是它没有实现 Illuminate\Contracts\Support\Jsonable