laravel vuejs/axios put request Formdata 为空

Posted

技术标签:

【中文标题】laravel vuejs/axios put request Formdata 为空【英文标题】:laravel vuejs/axios put request Formdata is empty 【发布时间】:2019-07-08 05:35:20 【问题描述】:

我有几个应用程序,当我使用 axios 发送表单数据时,post 数据已成功发送到 API。但是当我使用 put 请求时,它不适用于 formData。

<template>
  <div class="container">
    <div class="container-fluid" style="background:#fff">
      <div class="page-header">
        <h4 class="page-title">
          <i class="flaticon-users"></i> Leads
        </h4>
        <ul class="breadcrumbs">
          <li class="nav-home">
            <a href="/">
              <i class="flaticon-home"></i>
            </a>
          </li>
          <li class="separator">
            <i class="flaticon-right-arrow"></i>
          </li>
          <li class="nav-item">
            <router-link to="/leads">Leads</router-link>
          </li>
          <li class="separator">
            <i class="flaticon-right-arrow"></i>
          </li>
        </ul>
      </div>
      <template>
        <div class="btn-wrapper">
          <button v-on:click="seen = !seen" class="btn btn-primary btn-md">
            <i class="flaticon-interface-1"></i>Add New Lead
          </button>
        </div>
        <p></p>
      </template>
      <div class="row">
        <div class="col-md-12" v-if="!seen">
          <div class="card">
            <div class="card-header">
              <h4 class="card-title">
                <i class="flaticon-interface-1"></i> New Leads
              </h4>
            </div>
            <div class="card-body">
              <form
                @submit.prevent="addLeads"
                id="leadform"
                class="mb-3"
                enctype="multipart/form-data"
              >
                <div class="col-md-12">
                  <div class="row">
                    <div class="col-md-6">
                      <label>Lead</label>
                      <div class="form-group">
                        <input
                          type="text"
                          id="name"
                          name="lead_name"
                          class="form-control"
                          placeholder="Lead Name"
                          v-model="form.name"
                        >
                        <template v-if="errors">
                          <span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
                            <template v-if="fieldName == 'name'">
                              <p class="errors">
                                <strong> fieldsError.join('\n') </strong>
                              </p>
                            </template>
                          </span>
                        </template>
                      </div>
                    </div>

                    <div class="col-md-6">
                      <label>Source</label>
                      <div class="form-group">
                        <textarea
                          type="text"
                          id="source"
                          name="source"
                          class="form-control"
                          placeholder="lead Souve"
                          v-model="form.source"
                        ></textarea>

                        <template v-if="errors">
                          <span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
                            <template v-if="fieldName == 'source'">
                              <p class="errors">
                                <strong> fieldsError.join('\n') </strong>
                              </p>
                            </template>
                          </span>
                        </template>
                      </div>
                    </div>
                  </div>
                  <div class="row">
                    <div class="col-md-6">
                      <label>Value</label>
                      <div class="form-group">
                        <input
                          type="text"
                          id="value"
                          name="value"
                          class="form-control"
                          placeholder="lead Value"
                          v-model="form.value"
                        >

                        <template v-if="errors">
                          <span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
                            <template v-if="fieldName == 'value'">
                              <p class="errors">
                                <strong> fieldsError.join('\n') </strong>
                              </p>
                            </template>
                          </span>
                        </template>
                      </div>
                    </div>
                    <div class="col-md-6">
                      <label>Notes</label>
                      <div class="form-group">
                        <textarea
                          type="text"
                          id="notes"
                          name="notes"
                          class="form-control"
                          placeholder="lead Notes"
                          v-model="form.notes"
                        ></textarea>

                        <template v-if="errors">
                          <span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
                            <template v-if="fieldName == 'notes'">
                              <p class="errors">
                                <strong> fieldsError.join('\n') </strong>
                              </p>
                            </template>
                          </span>
                        </template>
                      </div>
                    </div>
                  </div>
                  <div class="row">
                    <div class="col-sm-6">
                      <div class="form-group">
                        <label for="exampleFormControlSelect1">Assigned To</label>
                        <template v-if="!userlist">
                          <select class="form-control" id="assigned_to">
                            <option value>No User Found</option>
                          </select>
                        </template>
                        <template v-else>
                          <select
                            v-model="form.assigned_to"
                            name="assigned_to"
                            class="form-control"
                            id="assigned_to"
                          >
                            <option value>Please Select</option>
                            <option v-for="user in userlist" :key="user.id" :value="user.id">
                              <template v-if="user.id == currentUser.id">Me</template>
                              <template v-else> user.name </template>
                            </option>
                          </select>
                        </template>
                        <template v-if="errors">
                          <span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
                            <template v-if="fieldName == 'assigned_to'">
                              <p class="errors">
                                <strong> fieldsError.join('\n') </strong>
                              </p>
                            </template>
                          </span>
                        </template>
                      </div>
                    </div>
                    <div class="col-sm-6">
                      <div class="form-group">
                        <label>Close Date</label>
                        <div class="clearfix"></div>
                        <date-picker v-model="form.date" name="close_date"></date-picker>
                      </div>
                    </div>
                  </div>
                  <div class="row">
                    <div class="col-md-6">
                      <label>Email</label>
                      <div class="form-group">
                        <input
                          type="text"
                          id="email"
                          name="email"
                          class="form-control"
                          placeholder="User Email"
                          v-model="form.email"
                        >

                        <template v-if="errors">
                          <span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
                            <template v-if="fieldName == 'email'">
                              <p class="errors">
                                <strong> fieldsError.join('\n') </strong>
                              </p>
                            </template>
                          </span>
                        </template>
                      </div>
                    </div>
                    <div class="col-md-6">
                      <label>Phone</label>
                      <div class="form-group">
                        <input
                          type="text"
                          id="phone"
                          name="phone"
                          class="form-control"
                          placeholder="User Phone Number"
                          v-model="form.phone"
                        >

                        <template v-if="errors">
                          <span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
                            <template v-if="fieldName == 'phone'">
                              <p class="errors">
                                <strong> fieldsError.join('\n') </strong>
                              </p>
                            </template>
                          </span>
                        </template>
                      </div>
                    </div>
                  </div>
                </div>
                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <input
                        type="file"
                        multiple="multiple"
                        id="attachments"
                        @change="uploadFieldChange"
                      >
                      <hr>
                      <div class="col-md-12">
                        <div
                          class="attachment-holder animated fadeIn"
                          v-cloak
                          v-for="(attachment, index) in attachments"
                        >
                          <template v-if="attachment.file_name">
                            <span class="label label-primary"> attachment.file_name</span>
                          </template>
                          <template v-else>
                            <span
                              class="label label-primary"
                            > attachment.name + ' (' + Number((attachment.size / 1024 / 1024).toFixed(1)) + 'MB)'</span>
                          </template>
                          <span
                            class
                            style="background: red; cursor: pointer;"
                            @click="removeAttachment(attachment)"
                          >
                            <button class="btn btn-xs btn-danger">Remove</button>
                          </span>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>

                <div class="row">
                  <div class="col-sm-6">
                    <div class="form-check">
                      <label>Status</label>
                      <br>
                      <label class="form-radio-label">
                        <input
                          class="form-radio-input"
                          v-model="form.status"
                          type="radio"
                          name="status"
                          value="open"
                          checked
                        >
                        <span class="form-radio-sign">Open</span>
                      </label>
                      <label class="form-radio-label ml-3">
                        <input
                          class="form-radio-input"
                          v-model="form.status"
                          type="radio"
                          name="status"
                          value="sent"
                        >
                        <span class="form-radio-sign">Proposal Sent</span>
                      </label>
                      <label class="form-radio-label ml-3">
                        <input
                          class="form-radio-input"
                          v-model="form.status"
                          type="radio"
                          name="status"
                          value="won"
                        >
                        <span class="form-radio-sign">Won</span>
                      </label>
                      <label class="form-radio-label ml-3">
                        <input
                          class="form-radio-input"
                          v-model="form.status"
                          type="radio"
                          name="status"
                          value="lost"
                        >
                        <span class="form-radio-sign">lost</span>
                      </label>
                    </div>
                  </div>
                </div>
                <div class="col-md-6">
                  <div class="form-group">
                    <button type="submit" class="btn btn-success">Save</button>
                    <button @click="clearForm()" class="btn btn-danger">Cancel</button>
                  </div>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="container-fluid" style="background:#fff;">
      <kanban-board :stages="stages" :blocks="blocks" @update-block="updateBlock">
        <div v-for="stage in stages" :slot="stage">
          <h2> stage </h2>
        </div>
        <div v-for="block in blocks" :slot="block.id">
          <div>
            <strong> block.name </strong>
          </div>
          <p></p>
          <button class="btn btn-danger">UKDH</button>
          <button class="btn btn-warning">£  block.value </button>
          <router-link :to="`/account/$block.id/convert`" class="btn btn-primary">create account</router-link>
          <div class="text-right">
            <router-link :to="`/leads/$block.id`" class="btn btn-link btn-info">
              <i class="la la-street-view"></i>
            </router-link>

            <a href="#" @click="deleteLead(block.id)" class="btn btn-link btn-danger">
              <i class="la la-times"></i>
            </a>
            <a href="#" @click="editLead(block)" class="btn btn-link btn-primary">
              <i class="la la-edit"></i>
            </a>
          </div>
        </div>
      </kanban-board>
    </div>
  </div>
</template>
<script>
import  addLeadsAPI  from "../../helpers/api";
import  updateStatus  from "../../helpers/api";
import  getCommonAPI  from "../../helpers/api";
import  deleteAPI  from "../../helpers/api";
import validate from "validate.js";
import DatePicker from "vue2-datepicker";

export default 
  name: "leads",
  components: 
    DatePicker
  ,
  data() 
    return 
      leads: [],
      userlist: [],
      attachments: [],
      percentCompleted: 0,
      upload_size: 0,
      result: ,
      stages: ["open", "sent", "lost", "won"],
      blocks: [],
      form: 
        id: "",
        name: "",
        source: "",
        value: 0,
        notes: "",
        user_id: "",
        assigned_to: 1,
        date: new Date(),
        email: "",
        phone: "",
        status: ""
      ,
      lead_id: "",
      pagination: ,
      edit: false,
      isOpen: 0,
      seen: true,
      errors: null
    ;
  ,
  created() 
    this.fetchLeads();
    this.getusers();
  ,
  mounted() 
    this.$store.dispatch("leads");
  ,
  methods: 
    getusers(page_url) 
      let vm = this;
      getCommonAPI("/users", "get", 
        headers: 
          Authorization: `Bearer $this.currentUser.token`,
          Accept: "application/json"
        
      ).then(res => 
        vm.userlist = res.data;
      );
    ,

    fetchLeads(page_url) 
      let vm = this;
      page_url = page_url || "/leads/lead";
      getCommonAPI(page_url, "get", 
        headers: 
          Authorization: `Bearer $this.currentUser.token`,
          Accept: "application/json"
        
      ).then(res => 
        vm.blocks = res.data.data;
        //vm.makePagination(res.meta, res.links);
      );
    ,
    makePagination(meta, links) 
      let pagination = 
        current_page: meta.current_page,
        last_page: meta.last_page,
        next_page_url: links.next,
        prev_page_url: links.prev
      ;
      this.pagination = pagination;
    ,
    editLead(form) 
      console.log(form);
      this.edit = true;
      this.seen = false;
      this.form.id = form.id;
      this.form.name = form.name;
      this.form.lead_sid = form.lead_sid;
      this.form.status = form.status;
      this.form.type = form.type;
      this.form.source = form.source;
      this.form.value = form.value;
      this.form.notes = form.notes;
      this.form.email = form.email;
      this.form.phone = form.phone;
      this.form.assigned_to = form.assigned_to;
      this.form.date = form.close_date;
      this.attachments = form.uploads;
    ,
    clearForm() 
      this.edit = false;
      this.form.id = null;
      this.form.user_id = null;
      this.form.assigned_to = "";
      this.form.type = "";
      this.form.status = true;
      this.form.name = "";
      this.form.source = "";
      this.form.value = "";
      this.form.notes = "";
      this.form.email = "";
      this.form.phone = "";
      this.attachments = [];
    ,
    addLeads() 
      if (this.edit === false) 
        // add new leads
        this.errors = null;
        const constraints = this.getConstraints();
        const errors = validate(this.$data.form, constraints);
        if (errors) 
          this.errors = errors;
          return;
        
        // multiple file uploading
        this.lead = document.getElementById("leadform");
        const formData = new FormData(this.lead);
        if (this.attachments.length > 0) 
          for (var i = 0; i < this.attachments.length; i++) 
            let attachment = this.attachments[i];
            formData.append("attachments[]", attachment);
          
        
        var config = 
          headers:  "Content-Type": "multipart/form-data" ,
          onUploadProgress: function(progressEvent) 
            this.percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            this.$forceUpdate();
          .bind(this)
        ;
        //end
        this.$store.dispatch("lead");

        addLeadsAPI(formData, "post").then(res => 
          swal("Good job!", "You clicked the button!", "success");
          this.clearForm();
          this.fetchLeads();
          //this.attachments = [];
        );
       else 
        this.errors = null;

        const constraints = this.getConstraints();
        const errors = validate(this.$data.form, constraints);
        if (errors) 
          this.errors = errors;
          return;
        
        console.log("i am in edit");
        // multiple file uploading
        this.lead = document.getElementById("leadform");
        let formData = new FormData(this.lead);
        if (this.attachments.length > 0) 
          for (var i = 0; i < this.attachments.length; i++) 
            let attachment = this.attachments[i];
            formData.append("attachments[]", attachment);
          
        
        console.log(formData);
        var config = 
          headers:  "Content-Type": "multipart/form-data" ,
          onUploadProgress: function(progressEvent) 
            this.percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            this.$forceUpdate();
          .bind(this)
        ;
        //end
        console.log(formData);
        this.$store.dispatch("lead");
        //update
        addLeadsAPI(formData, "put").then(res => 
          swal("Good job!", "You clicked the button!", "success");
          this.clearForm();
          this.fetchLeads();
          //this.attachments = [];
        );
      
    ,
    getConstraints() 
      return 
        name: 
          presence: true,
          length: 
            minimum: 6,
            message: "Must be at least 6 characters long"
          
        ,
        source: 
          presence: true,
          length: 
            minimum: 6,
            message: "Must be at least 6 characters long"
          
        ,
        value: 
          presence: true,
          length: 
            minimum: 1,
            message: "Must be at least 1 characters long"
          
        ,
        notes: 
          presence: true,
          length: 
            minimum: 6,
            message: "Must be at least 6 characters long"
          
        
      ;
    ,
    updateBlock(id, status) 
      //api call axios
      updateStatus(id, status, "get").then(res => 
        this.clearForm();
        this.fetchLeads();
      );
      this.blocks.find(b => b.id === Number(id)).status = status;
    ,
    deleteLead(id) 
      swal(
        title: "Are you sure?",
        text: "Do you really want to delete Lead!",
        type: "warning",
        buttons: 
          confirm: 
            text: "Yes, delete it!",
            className: "btn btn-success"
          ,
          cancel: 
            visible: true,
            className: "btn btn-danger"
          
        
      ).then(Delete => 
        if (Delete) 
          deleteAPI(`/lead/$id`, "delete", 
            headers: 
              Authorization: `Bearer $this.currentUser.token`,
              Accept: "application/json"
            
          ).then(res => 
            swal(
              title: "Deleted!",
              text: "Your lead has been deleted.",
              type: "success",
              buttons: 
                confirm: 
                  className: "btn btn-success"
                
              
            );
            this.fetchLeads();
          );
         else 
          this.fetchLeads();
          swal.close();
        
      );
    ,
    getAttachmentSize() 
      this.upload_size = 0; // Reset to beginningƒ
      this.attachments.map(item => 
        this.upload_size += parseInt(item.size);
      );

      this.upload_size = Number(this.upload_size.toFixed(1));
      this.$forceUpdate();
    ,

    removeAttachment(attachment) 
      this.attachments.splice(this.attachments.indexOf(attachment), 1);

      this.getAttachmentSize();
    ,
    // This function will be called every time you add a file
    uploadFieldChange(e) 
      console.log(this.attachments);
      var files = e.target.files || e.dataTransfer.files;
      if (!files.length) return;
      for (var i = files.length - 1; i >= 0; i--) 
        this.attachments.push(files[i]);
      
      console.log("out");
      // Reset the form to avoid copying these files multiple times into this.attachments
      document.getElementById("attachments").value = [];
    
  ,
  computed: 
    users() 
      return this.$store.getters.users;
    ,

    currentUser() 
      return this.$store.getters.currentUser;
    
  
;
</script>
<style lang="scss">
@import "../assets/board.scss";
</style>
<style scoped>
.vue-js-switch#changed-font 
  font-size: 30px;

.hide 
  display: none;

.errors 
  color: lightcoral;
  border-radius: 5px;
  padding: 21px 0 2px 0;

</style>

edit 选项为真时。我正在调用方法addLeadsAPI 以使用axios put 发布数据,但Formdata 为空$request-&gt;all()

任何人都可以帮助我吗?似乎axios put 不适用于编辑数据。通过表单数据。

【问题讨论】:

***.com/questions/62535510/put-form-data-axios-vue-js/… 【参考方案1】:

可能与此有关,https://laravel.com/docs/5.0/routing#method-spoofing。 当使用 PUT、PATCH 或 DELETE 时,您可能还需要让 laravel 知道您正在使用的表单方法。尝试添加值为“PUT”的“_method”属性,让我知道这是否适合您

【讨论】:

【参考方案2】:

Laravel 不能用 PUT 方法很好地处理 multipart-formdata。见Input from PUT requests sent as multipart/form-data is unavailable #13457。

如果你的代码实际使用了PUT方法,似乎是受到了这个问题的影响。

有几种解决方法。

与客户端打交道:

使用 POST 方法而不是 PUT 方法,并将 _method 参数值设置为 PUT(称为“方法欺骗”)

处理服务器端:

向 Laravel 添加一个执行多部分处理的包。 (例如illuminatech/multipart-middleware) 使用pecl/apfd 扩展,它可以为任何请求方法解析“multipart/form-data”HTTP 请求。

【讨论】:

是的,我已经通过使用 post 方法而不是 put 解决了这个问题。【参考方案3】:

我已将axioscall 更改为post 并设置值_method:put

addLeads() 
      if (this.edit === false) 
        // add new leads
        this.errors = null;
        const constraints = this.getConstraints();
        const errors = validate(this.$data.form, constraints);
        if (errors) 
          this.errors = errors;
          return;
        
        // multiple file uploading
        this.lead = document.getElementById("leadform");
        const formData = new FormData(this.lead);
        if (this.attachments.length > 0) 
          for (var i = 0; i < this.attachments.length; i++) 
            let attachment = this.attachments[i];
            formData.append("attachments[]", attachment);
          
        
        var config = 
          headers:  "Content-Type": "multipart/form-data" ,
          onUploadProgress: function(progressEvent) 
            this.percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            this.$forceUpdate();
          .bind(this)
        ;
        //end
        this.$store.dispatch("lead");
        formData.append("_method", "post");
        addLeadsAPI(formData, "post", config).then(res => 
          swal("Good job!", "You clicked the button!", "success");
          this.clearForm();
          this.fetchLeads();
          //this.attachments = [];
        );
       else 
        this.errors = null;

        const constraints = this.getConstraints();
        const errors = validate(this.$data.form, constraints);
        if (errors) 
          this.errors = errors;
          return;
        
        console.log("i am in edit");
        // multiple file uploading
        this.lead = document.getElementById("leadform");
        let formData = new FormData(this.lead);
        if (this.attachments.length > 0) 
          for (var i = 0; i < this.attachments.length; i++) 
            let attachment = this.attachments[i];
            formData.append("attachments[]", attachment);
          
        
        formData.append("_method", "put");
        formData.append("id", this.form.id);
        console.log(formData);
        var config = 
          headers:  "Content-Type": "application/x-www-form-urlencoded" ,
          onUploadProgress: function(progressEvent) 
            this.percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            this.$forceUpdate();
          .bind(this)
        ;
        //end
        console.log(formData);
        this.$store.dispatch("lead");
        //update
        addLeadsAPI(formData, "put", config).then(res => 
          swal("Good job!", "You clicked the button!", "success");
          this.clearForm();
          this.fetchLeads();
          //this.attachments = [];
        );
      
    ,

【讨论】:

【参考方案4】:

好吧,我在尝试使用 axiosvue.js 更新记录时遇到了问题。

解决方法是将formData上的method值设置为put,并使用post方法发送请求。像这样的:

console.log("i am in edit");
    // multiple file uploading
    this.lead = document.getElementById("leadform");
    let formData = new FormData(this.lead);
    if (this.attachments.length > 0) 
      for (var i = 0; i < this.attachments.length; i++) 
        let attachment = this.attachments[i];
        formData.append("attachments[]", attachment);
      
    
    formData.append("_method", "put");
    console.log(formData);

【讨论】:

以上是关于laravel vuejs/axios put request Formdata 为空的主要内容,如果未能解决你的问题,请参考以下文章

CORS 块 Laravel + VueJS Axios

Vuejs Axios POST 请求从 Laravel 后端获取 HTTP422 错误

Laravel VueJS Axios 将数组发送到控制器

Laravel VueJS,Axios 看不到 CORS 标头,但 Postman 和浏览器可以

VueJs Axios Access-Control-Allow-Origin CORS 错误

VueJs Axios - 请求标头