Vue-resource + FormData 文件上传与 Laravel 后端

Posted

技术标签:

【中文标题】Vue-resource + FormData 文件上传与 Laravel 后端【英文标题】:Vue-resource + FormData File Upload with Laravel Backend 【发布时间】:2018-04-15 17:33:21 【问题描述】:

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

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

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

为了测试我的上传,我的控制器返回一个 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'" >
                            </label>
                            <div class="avatar" @click="reset" v-if="filepath">
                                <img :src="filepath" >
                            </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

【问题讨论】:

你能给我看看服务器端代码吗? 我更新了我的帖子 :) 【参考方案1】:

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

您的文件正在上传,请尝试检查一下

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

你会得到文件名作为响应。

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

【讨论】:

我明白你的意思,但 $request->file('avatar') 返回 null,我试图调用 _toString() 和 getClientOriginalName() .. 没有成功我拿了一个 500:“消息": "在 null 上调用成员函数 getClientOriginalName()" 你能告诉我错误吗,因为我已经在我的机器上复制了你的代码进行测试,它工作得很好。 救了我一天!

以上是关于Vue-resource + FormData 文件上传与 Laravel 后端的主要内容,如果未能解决你的问题,请参考以下文章

vue-resource发送post请求服务器接收不到数据

Vue-resource中post请求将data数据以request payload转换为form data的形式

vue-resource

vue-resource

vue系列之vue-resource

vue-resource