首页 文章

使用Laravel在Vue组件中上传图像

提问于
浏览
0

我正在制作一个具有上传图像功能的简单网站 . 我尝试了Laravel方式,我在刀片模板中制作它,它工作正常 . 现在我想在Vue Components中创建它

这是我的 Create.vue

<template>
  <div>

	 <div class="row">
		<input type="hidden" name="_token" :value="csrf">
		<div class="col-md-5">
			<div class="detail-container">
				<label for="title">Book Title:</label>
				<input type="text" name="title" id="title" v-model="book_title" class="form-control">
			</div>
			<div class="detail-container">
				<label for="title">Book Description:</label>
				<textarea type="text" name="description" id="description" v-model="book_description" class="form-control" rows="5"></textarea>
			</div>
			<div class="detail-container">
				<label for="title">Tags:</label>
				<multiselect v-model="tags" :show-labels="false" name="selected_tags" :hide-selected="true" tag-placeholder="Add this as new tag" placeholder="Search or add a tag" label="name" track-by="id" :options="tagsObject" :multiple="true" :taggable="true" @tag="addTag" @input="selectTags">
				<template slot="selection" slot-scope="tags"></template>
				</multiselect>
			</div>
		</div>

		<div class="col-md-7">
			<!-- BOOK COVER WILL GO HERE -->
			<div class="detail-container">
				<label>Book Cover:</label>
				<input type="file" class="form-control-file" id="book_cover" name="selected_cover" @change="onFileChange">
				<small id="fileHelp" class="form-text text-muted">After you select your desired cover, it will show the preview of the photo below.</small>
				<div id="preview">
					<img v-if="url" :src="url" height="281" width="180" />
				</div>
			</div>
		</div>
		<div class="detail-container" style="margin-top: 20px;">
			<button class="btn btn-primary" @click="saveBook()">Next</button>
		</div>
  </div>
  </div>
</template>

<script>
	import Multiselect from 'vue-multiselect'

	// register globally
	Vue.component('multiselect', Multiselect)

	export default {
		// OR register locally
		components: { Multiselect },
		data () {
			return {
				csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
				url: null,
				selected_cover: null,
				tags: [],
				tagsObject: [],
				selected_tags: [],
				book_title: '',
				book_description: ''
			}
		},
		methods: {
			getTags() {
				let vm = this;
				axios.get('/admin/getTags').then(function(result){
					let data = result.data;
					for(let i in data) {
						vm.tagsObject.push({id: data[i].id, name: data[i].name});
					}
				});
			},
			addTag (newTag) {
				const tag = {
					name: newTag,
					id: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
				}
				this.tagsObject.push(tag);
				this.tags.push(tag);
			},
			selectTags(value) {
				this.selected_tags = value.map(a=>a.id);
			},
			onFileChange(e) {
			  const file = e.target.files[0];
			  this.url = URL.createObjectURL(file);
			  this.selected_cover = file;
			},
			saveBook() {
				const fd = new FormData();
				fd.append('image', this.selected_cover, this.selected_cover.name)
				console.log(this.selected_cover);
				var book_details = {
					'title': this.book_title,
					'description': this.book_description,
					'book_cover': this.selected_cover,
					'tags': this.selected_tags
				};
				
				axios.post('/admin/saveBook', book_details).then(function(result){
					console.log('done')
				})
			}
		},
		created() {
			this.getTags();
		}
	}
</script>

<!-- New step!
	 Add Multiselect CSS. Can be added as a static asset or inside a component. -->
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

这是我的控制器

public function store(Request $request)
{

     $this->validate(request(), [
        'title' => 'required|min:5',
        'description' => 'required|min:10',
        'book_cover' => 'required|image|mimes:jpeg,jpg,png|max:10000'
     ]);
    // File Upload
    if($request->hasFile('book_cover')) {
        $fileNameWithExt = $request->file('book_cover')->getClientOriginalName();
        // GET FILE NAME
        $filename = pathinfo($fileNameWithExt, PATHINFO_FILENAME);
        // GET EXTENSION
        $extension = $request->file('book_cover')->getClientOriginalExtension();
        // File Unique Name
        $fileNameToStore = $filename. '_'. time().'.'.$extension;
        $path = $request->file('book_cover')->storeAs('public/book_covers', $fileNameToStore);
    } else {
        $fileNameToStore = 'noimage.jpg';
    }

    $book = new Book;
    $book->title = request('title');
    $book->description = request('description');
    $book->book_cover = $fileNameToStore;
    $book->save();

    $book->tags()->sync($request->tags, false);

    return back()->with('success', 'Book Created Successfully!');

}

我从未碰过我的控制器,因为这是我在Laravel Way中使用此功能时所使用的,但是当我保存它时,细节正在保存,但图像没有上传,而是在数据库中保存noimage.jpg . 有谁知道我做错了什么?

我试图在 book_details 中添加此部分 const fd = new FormData(); 但是当我 console.log(fd) 它没有返回任何数据 .

1 回答

  • 0

    你应该在你的POST请求中传递fd对象而不是book_details .

    你可以做到这样的事情 .

    onFileChange(e) {
        const file = e.target.files[0];
        // this.url = URL.createObjectURL(file);
        this.selected_cover = file;
    },
    saveBook() {
        const fd = new FormData();
        fd.append('image', this.selected_cover)
        fd.append('title', this.book_title)
        fd.append('description', this.book_description)
        fd.append('book_cover', URL.createObjectURL(this.selected_cover))
        fd.append('tags', this.selected_tags)
    
        axios.post('/admin/saveBook', fd).then(function(result){
            console.log('done')
        })
    }
    

    而且,你不能只是 console.log 在控制台中的fd . 你可以做的是这样的事情

    for (var pair of fd.entries()) {
        console.log(pair[0]+ ', ' + pair[1]); 
    }
    

    FormData是一种特殊类型的对象,它不是可字符串化的,不能使用console.log打印出来 . (链接)

相关问题