php - 将文件从 VueJS 应用程序上传到 Laravel 中的 API

标签 php laravel http vue.js laravel-5.5

我正在尝试将文件(Excel 工作表)从使用 VueJS 构建的前端应用程序上传到使用 Laravel 5.5 构建的 API。我有一些表单请求验证,它告诉我文件字段是必需的。因此该文件根本不会上传到我的 API。

VueJS文件上传:

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.form 是从 this project 复制的 Form 类但 data() 方法返回 FormData对象而不是对象。

data()方法:

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

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

    return data;
}

路线:

enter image description here

表单请求规则:

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

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

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

编辑( Controller 功能)

public function update(ImportRequest $request, CoursesImport $file)
{
    $courses = $file->handleImport();

    dispatch(new StartCourseUploading($courses, currentUser()));

    $file->delete();

    return ok();
}

最佳答案

您收到的状态为 422,我希望您根据您的响应类的规则了解此含义,因为验证失败

在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

我的代码示例

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.');
        });
    }
  }
});
<!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/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4432312104766a756a72" rel="noreferrer noopener nofollow">[email protected]</a>/dist/vue.js"></script>

</body>

</html>

相关链接

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

关于php - 将文件从 VueJS 应用程序上传到 Laravel 中的 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46192301/

相关文章:

php - 在云上托管的 Laravel 应用程序上配置缓存服务器

php - 拉维尔 5 : app() helper function

.net - HttpWebRequest - POST 中不允许使用括号

php - Symfony 2 带有 PUGXMultiUserBundle 和多登录表单

php - 如何获取 GROUP BY 查询的总行数?

javascript - 在 Laravel/Vue.js 项目中共享静态/配置数据的最佳方式是什么

javascript - API、后端和前端作为所有三个独立的组件

ajax - 浏览器不能只使用之前 ajax 调用的缓存吗?

java - 网站安全: what does it mean to infect people with silent java drive?

php - zend 框架选择对象和复杂连接