将文件从 VueJS 应用程序上传到 Laravel 中的 API
Upload file from VueJS app to API in Laravel
我正在尝试将文件 (Excel sheet) 从使用 VueJS 构建的 front-end 应用程序上传到使用 Laravel 5.5 构建的 API .我有一些表单请求验证对我说 The file field is required
。所以文件根本没有上传到我的 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 but the data()
method returns a FormData 对象而不是对象复制的表单 class。
data()
方法:
data() {
let data = new FormData();
for (let property in this.originalData) {
data.append(property, this[property]);
}
return data;
}
路线:
表单请求规则:
public function rules()
{
return [
'file' => 'required',
];
}
如果我查看 Chrome DevTools 中的“网络”选项卡,似乎请求已正确发送:(image after click).
我尝试了很多方法,比如将 excel 作为 base64 发送到 api。但后来我无法正确解码。所以现在我正在尝试这个,但我无法解决问题。
编辑(控制器功能)
public function update(ImportRequest $request, CoursesImport $file)
{
$courses = $file->handleImport();
dispatch(new StartCourseUploading($courses, currentUser()));
$file->delete();
return ok();
}
您的状态为 422
,根据您的 回复 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 的路线。
其他注意事项:
确保添加了 属性 类以下代码
data: {
form: new Form({
file:null
})
},
检查浏览器请求天气发送表单数据是否正确,我添加了示例屏幕截图
我的代码示例
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/vue@2.1.6/dist/vue.js"></script>
</body>
</html>
相关链接
如果您将数据存储在关联数组中,例如数据:
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);
});
我正在尝试将文件 (Excel sheet) 从使用 VueJS 构建的 front-end 应用程序上传到使用 Laravel 5.5 构建的 API .我有一些表单请求验证对我说 The file field is required
。所以文件根本没有上传到我的 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 but the data()
method returns a FormData 对象而不是对象复制的表单 class。
data()
方法:
data() {
let data = new FormData();
for (let property in this.originalData) {
data.append(property, this[property]);
}
return data;
}
路线:
表单请求规则:
public function rules()
{
return [
'file' => 'required',
];
}
如果我查看 Chrome DevTools 中的“网络”选项卡,似乎请求已正确发送:(image after click).
我尝试了很多方法,比如将 excel 作为 base64 发送到 api。但后来我无法正确解码。所以现在我正在尝试这个,但我无法解决问题。
编辑(控制器功能)
public function update(ImportRequest $request, CoursesImport $file)
{
$courses = $file->handleImport();
dispatch(new StartCourseUploading($courses, currentUser()));
$file->delete();
return ok();
}
您的状态为 422
,根据您的 回复 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 的路线。
其他注意事项:
确保添加了 属性 类以下代码
data: { form: new Form({ file:null }) },
检查浏览器请求天气发送表单数据是否正确,我添加了示例屏幕截图
我的代码示例
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/vue@2.1.6/dist/vue.js"></script>
</body>
</html>
相关链接
如果您将数据存储在关联数组中,例如数据:
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);
});