将文件从VueJS app上传到Laravel中的API

时间:2017-09-13 08:13:06

标签: php laravel http vue.js laravel-5.5

我正在尝试从使用VueJS的前端应用版本上传文件(Excel工作表)到使用Laravel 5.5的API版本。我有一些表单请求验证,它告诉我Standalone.xml。因此,该文件根本不会上传到我的API。

VueJS文件上传:

The file field is required

onFileChange(e) { let files = e.target.files || e.dataTransfer.files; if (files.length <= 0) { return; } this.upload(files[0]); }, upload(file) { this.form.file = file; this.form.put('courses/import') .then((response) => { alert('Your upload has been started. This can take some time.'); }) .catch((response) => { alert('Something went wrong with your upload.'); }); } 是从this project复制的Form类,但this.form方法返回FormData对象而不是对象。

data()方法:

data()

路线:

enter image description here

FormRequest规则:

data() {
    let data = new FormData();

    for (let property in this.originalData) {
        data.append(property, this[property]);
    }

    return data;
}

如果我查看Chrome DevTools中的“网络”标签,似乎请求发送正确:(image after click)

我尝试了很多东西,例如将excel作为base64发送到api。但后来我无法正确解码。所以现在我正在尝试这个,但我无法解决问题。

编辑(控制器功能)

public function rules()
{
    return [
        'file' => 'required',
    ];
}

2 个答案:

答案 0 :(得分:2)

您的状态为422,我希望您根据 Responses class 的规则了解验证失败的含义。

在laravel中,PUT方法不接受文件上传,因此您需要从PUT更改为POST。

this.form.post('courses/import')
    .then((response) => {
      alert('Your upload has been started. This can take some time.');
    })
    .catch((response) => {
      alert('Something went wrong with your upload.');
    });

不要忘记更新您的laravel路线

其他考虑因素:

  1. 确保添加以下代码的属性类型

    data: {
        form: new Form({
            file:null
        })
    },
    
  2. 检查浏览器请求天气是否正确发送表单数据,我添加了示例屏幕截图Request

  3. 我的代码示例

    &#13;
    &#13;
    class Errors {
      /**
       * Create a new Errors instance.
       */
      constructor() {
        this.errors = {};
      }
    
    
      /**
       * Determine if an errors exists for the given field.
       *
       * @param {string} field
       */
      has(field) {
        return this.errors.hasOwnProperty(field);
      }
    
    
      /**
       * Determine if we have any errors.
       */
      any() {
        return Object.keys(this.errors).length > 0;
      }
    
    
      /**
       * Retrieve the error message for a field.
       *
       * @param {string} field
       */
      get(field) {
        if (this.errors[field]) {
          return this.errors[field][0];
        }
      }
    
    
      /**
       * Record the new errors.
       *
       * @param {object} errors
       */
      record(errors) {
        this.errors = errors;
      }
    
    
      /**
       * Clear one or all error fields.
       *
       * @param {string|null} field
       */
      clear(field) {
        if (field) {
          delete this.errors[field];
    
          return;
        }
    
        this.errors = {};
      }
    }
    
    
    class Form {
      /**
       * Create a new Form instance.
       *
       * @param {object} data
       */
      constructor(data) {
        this.originalData = data;
    
        for (let field in data) {
          this[field] = data[field];
        }
    
        this.errors = new Errors();
      }
    
    
      /**
       * Fetch all relevant data for the form.
       */
      data() {
        let data = new FormData();
    
        for (let property in this.originalData) {
          data.append(property, this[property]);
        }
    
        return data;
      }
    
    
      /**
       * Reset the form fields.
       */
      reset() {
        for (let field in this.originalData) {
          this[field] = '';
        }
    
        this.errors.clear();
      }
    
    
      /**
       * Send a POST request to the given URL.
       * .
       * @param {string} url
       */
      post(url) {
        return this.submit('post', url);
      }
    
    
      /**
       * Send a PUT request to the given URL.
       * .
       * @param {string} url
       */
      put(url) {
        return this.submit('put', url);
      }
    
    
      /**
       * Send a PATCH request to the given URL.
       * .
       * @param {string} url
       */
      patch(url) {
        return this.submit('patch', url);
      }
    
    
      /**
       * Send a DELETE request to the given URL.
       * .
       * @param {string} url
       */
      delete(url) {
        return this.submit('delete', url);
      }
    
    
      /**
       * Submit the form.
       *
       * @param {string} requestType
       * @param {string} url
       */
      submit(requestType, url) {
        return new Promise((resolve, reject) => {
          axios[requestType](url, this.data())
            .then(response => {
              this.onSuccess(response.data);
    
              resolve(response.data);
            })
            .catch(error => {
              this.onFail(error.response.data);
    
              reject(error.response.data);
            });
        });
      }
    
    
      /**
       * Handle a successful form submission.
       *
       * @param {object} data
       */
      onSuccess(data) {
        alert(data.message); // temporary
    
        this.reset();
      }
    
    
      /**
       * Handle a failed form submission.
       *
       * @param {object} errors
       */
      onFail(errors) {
        this.errors.record(errors);
      }
    }
    
    
    var app = new Vue({
      el: '#app',
    
      data: {
        form: new Form({
          file: ''
        })
      },
      methods: {
        onSubmit() {
          this.form.post('/projects')
            .then(response => alert('Wahoo!'));
        },
        onFileChange(e) {
          let files = e.target.files || e.dataTransfer.files;
    
          if (files.length <= 0) {
            return;
          }
    
          this.upload(files[0]);
        },
        upload(file) {
          this.form.file = file;
    
          this.form.post('courses/import')
            .then((response) => {
              alert('Your upload has been started. This can take some time.');
            })
            .catch((response) => {
              alert('Something went wrong with your upload.');
            });
        }
      }
    });
    &#13;
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.css">
      <style>
        body {
          padding-top: 40px;
        }
      </style>
    </head>
    
    <body>
      <div id="app" class="container">
    
    
        <form method="POST" action="/projects" @submit.prevent="onSubmit" @keydown="form.errors.clear($event.target.name)">
    
          <input type="file" name="image" @change="onFileChange">
            
          <div class="control">
            <button class="button is-primary" :disabled="form.errors.any()">Create</button>
          </div>
        </form>
      </div>
    
      <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.js"></script>
      <script src="https://unpkg.com/vue@2.1.6/dist/vue.js"></script>
    
    </body>
    
    </html>
    &#13;
    &#13;
    &#13;

    相关链接

    https://github.com/laravel/framework/issues/17560

答案 1 :(得分:0)

如果将数据存储在关联数组中,例如data:

var formData = new FormData();
Object.keys(data).forEach(function(key, index){
    if(Array.isArray(data[key])){
        formData.append(key + '[]', data[key]);
    } else {
        formData.append(key, data[key]);
    }
});
formData.append('file', document.getElementById('file_id').files[0]);
axios.post('path', formData).then( res => {
    console.log(res);
}).catch(res => {
    console.log(res);
});