Dropzone 在后端 Laravel 中没有有效的 MIME 类型?
Dropzone no valid MIME type in backend Laravel?
老实说,我真的不知道问题出在哪里。
可能是 Dropzone,Laravel (5.4),...所以我真的希望即使是一个想法也能帮助我解决这个问题。
当我上传文件时,我没有遇到任何 js 问题,但是 Laravel 抛出以下错误(对于每个文件):
调用未定义的方法 Symfony\Component\HttpFoundation\File\UploadedFile::store()
这是我的后端代码(在 portfolioStore 方法中设置了错误):
<?php
namespace App\Http\Controllers;
use App\Http\Requests\UploadPortfolioPhotoRequest; use App\PortfolioPhoto; use DebugBar\DebugBar; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage;
class AdminController extends Controller {
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('admin.home');
}
public function portfolioIndex()
{
$photos = PortfolioPhoto::all();
return view ('admin.portfolio.index')->with('photos', $photos);
}
public function portfolioStore(UploadPortfolioPhotoRequest $request)
{
foreach ($request->files as $photo) {
$filename = $photo->store('photos');
$test = PortfolioPhoto::create([
'filename' => $filename,
'title' => 'title',
'alt' => 'alt'
]);
}
return 'Upload successful!';
}
public function portfolioDelete()
{
return view ('admin.portfolio.index');
} }
无论如何,这是我的 Dropzone 配置:
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(document.body, { // Make the whole body a dropzone
url: "/admin/portfolio", // Set the url
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoDiscover: false,
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: "#previews", // Define the container to display the previews
clickable: ".fileinput-button", // Define the element that should be used as click trigger to select files.
headers: {
'x-csrf-token': document.querySelectorAll('meta[name=csrf-token]')[0].getAttributeNode('content').value,
}
});
myDropzone.on("addedfile", function(file) {
// Hookup the start button
file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
});
myDropzone.on("sending", function(file) {
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
// Hide the total progress bar when nothing's uploading anymore
myDropzone.on("queuecomplete", function(progress) {
var alertMsg = document.createElement('div'),
actions = document.getElementById('actions');
alertMsg.setAttribute('class', 'alert bg-success');
alertMsg.innerHTML = 'Files successfully uploaded<a href="#" class="pull-right"><em class="fa fa-lg fa-close"></em></a>';
actions.parentNode.insertBefore(alertMsg, actions.nextSibling);
});
// Setup the buttons for all transfers
// The "add files" button doesn't need to be setup because the config
// `clickable` has already been specified.
document.querySelector("#actions .start").onclick = function() {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function() {
myDropzone.removeAllFiles(true);
};
视图如下:
@extends('admin.layouts.app')
@section('content')
<div class="row">
<div class="col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Upload images</div>
<div class="panel-body">
@if (count($errors) > 0)
<div class="row">
<div class="col-xs-12">
<div class="alert bg-danger" role="alert"><em class="fa fa-lg fa-warning"> </em>
<ul style="display: inline-block;">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
<a href="#" class="pull-right"><em class="fa fa-lg fa-close"></em></a>
</div>
</div>
</div>
@endif
<div id="actions" class="row">
<div class="col-xs-12">
<div class="form-group">
<button class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i><span>Add files...</span>
</button>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i> <span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel upload</span>
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="files" id="previews">
<div id="template" class="file-row">
<div class="media">
<div class="media-left">
<img data-dz-thumbnail/>
</div>
<div class="media-body">
<h4 class="media-heading name" data-dz-name></h4>
<div class="col-xs-12"><strong class="error text-danger" data-dz-errormessage></strong></div>
<div class="col-xs-12">
<div class="col-sm-3">
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</div>
<div class="col-sm-9 text-right">
<button class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Portfolio</div>
<div class="panel-body">
<div class="row">
@foreach($photos as $photo)
<div class="col-xs-6 col-md-3">
<a href="#" class="thumbnail">
<img src="..." alt="...">
</a>
</div>
@endforeach
</div>
</div>
</div>
</div>
</div>@endsection
@push('styles')
<link href="{{asset('css/vendor/dropzone.css')}}"/>
@endpush
@push('scripts')
<script src="{{asset('js/vendor/dropzone.js')}}"></script>
<script src="{{asset('js/vendor/initialize/dropzone.cfg.js')}}"></script>
@endpush
所以现在我想知道这个问题是否与未定义的 MIME 类型有关,从而导致存储方法无法工作。还是我应该去别处看看?
欢迎任何建议和想法:)
这对我来说似乎不是 dropzone.js 的问题。
该错误在后端 (laravel) 中显示 "undefined method...",因此该方法对您的对象 photo
.
不可用
查看 laravel 中的文档。 (https://laravel.com/docs/5.4/filesystem#file-uploads)
也许你可以尝试这样的事情:
foreach ($request->files as $photo) {
$path = Storage::putFile('photos', $photo);
...
已更新
在 Laravel 您访问上传的文件 using the file
method, which takes the name of the file input as a parameter. And from the Dropzonejs docs:
The uploaded files can be handled just as if there would have been a html input like this:
<input type="file" name="file" />
所以试试这个:
foreach ($request->file('file') as $photo) {
只需转储您的 $request 对象,dropzone 可能会发送 base64_encoded 个不在 $request->files 数组中的图像。
另外,你可以使用
https://github.com/bnbwebexpertise/laravel-attachments
这是处理文件非常有用的软件包。
这里的问题是 $request->files
在 Laravel 代码库中不存在。由于 Illuminate\Http\Request
class 扩展了 Symfony\Component\HttpFoundation\Request
class,files
refers to Symfony\Component\HttpFoundation\FileBag
class 确实发生了包含大量没有存储方法的 Symfony\Component\HttpFoundation\File\UploadedFile
。
简单修复:
将 $request->files
替换为 $request->allFiles()
,这应该会为您提供一个 Illuminate\Http\UploadedFile
class 数组,其中包含存储方法
如果您需要进一步的帮助,请随时在评论部分提出任何问题
我有一个类似的问题,但在我的例子中,只是没有 enctype="multipart/form-data"
属性 包含在 <form>
标签中。一旦我这样做了,它就奏效了。而且我看到你也没有 <form>
标签。
<form action="/route" method="post" enctype="multipart/form-data">
<!-- your code for dropzone goes here -->
</form>
另外,在 AdminController
控制器的 portfolioStore()
方法中,
foreach ($request->allFiles() as $photo) {
$filename = $photo->store('photos');
$test = PortfolioPhoto::create([
'filename' => $filename,
'title' => 'title',
'alt' => 'alt'
]);
}
请不要这样做!
您在此处创建的插入查询过多。
重构如下。你可以摆脱一个数据库查询:)
$photos = [];
foreach ($request->files as $photo) {
$filename = $photo->store('photos');
$photos[] = [
'filename' => $filename,
'title' => 'title',
'alt' => 'alt'
];
}
PortfolioPhoto::createMany($photos);
并且在之前的 post 中,我回答了如何方便地在 Laravel 中存储文件。你可以。它可以改善您的 $filename = $photo->store('photos');
部分。
希望这对您有所帮助:)
老实说,我真的不知道问题出在哪里。
可能是 Dropzone,Laravel (5.4),...所以我真的希望即使是一个想法也能帮助我解决这个问题。
当我上传文件时,我没有遇到任何 js 问题,但是 Laravel 抛出以下错误(对于每个文件):
调用未定义的方法 Symfony\Component\HttpFoundation\File\UploadedFile::store()
这是我的后端代码(在 portfolioStore 方法中设置了错误):
<?php
namespace App\Http\Controllers;
use App\Http\Requests\UploadPortfolioPhotoRequest; use App\PortfolioPhoto; use DebugBar\DebugBar; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage;
class AdminController extends Controller {
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('admin.home');
}
public function portfolioIndex()
{
$photos = PortfolioPhoto::all();
return view ('admin.portfolio.index')->with('photos', $photos);
}
public function portfolioStore(UploadPortfolioPhotoRequest $request)
{
foreach ($request->files as $photo) {
$filename = $photo->store('photos');
$test = PortfolioPhoto::create([
'filename' => $filename,
'title' => 'title',
'alt' => 'alt'
]);
}
return 'Upload successful!';
}
public function portfolioDelete()
{
return view ('admin.portfolio.index');
} }
无论如何,这是我的 Dropzone 配置:
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var myDropzone = new Dropzone(document.body, { // Make the whole body a dropzone
url: "/admin/portfolio", // Set the url
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoDiscover: false,
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: "#previews", // Define the container to display the previews
clickable: ".fileinput-button", // Define the element that should be used as click trigger to select files.
headers: {
'x-csrf-token': document.querySelectorAll('meta[name=csrf-token]')[0].getAttributeNode('content').value,
}
});
myDropzone.on("addedfile", function(file) {
// Hookup the start button
file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
});
myDropzone.on("sending", function(file) {
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
// Hide the total progress bar when nothing's uploading anymore
myDropzone.on("queuecomplete", function(progress) {
var alertMsg = document.createElement('div'),
actions = document.getElementById('actions');
alertMsg.setAttribute('class', 'alert bg-success');
alertMsg.innerHTML = 'Files successfully uploaded<a href="#" class="pull-right"><em class="fa fa-lg fa-close"></em></a>';
actions.parentNode.insertBefore(alertMsg, actions.nextSibling);
});
// Setup the buttons for all transfers
// The "add files" button doesn't need to be setup because the config
// `clickable` has already been specified.
document.querySelector("#actions .start").onclick = function() {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function() {
myDropzone.removeAllFiles(true);
};
视图如下:
@extends('admin.layouts.app')
@section('content')
<div class="row">
<div class="col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Upload images</div>
<div class="panel-body">
@if (count($errors) > 0)
<div class="row">
<div class="col-xs-12">
<div class="alert bg-danger" role="alert"><em class="fa fa-lg fa-warning"> </em>
<ul style="display: inline-block;">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
<a href="#" class="pull-right"><em class="fa fa-lg fa-close"></em></a>
</div>
</div>
</div>
@endif
<div id="actions" class="row">
<div class="col-xs-12">
<div class="form-group">
<button class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i><span>Add files...</span>
</button>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i> <span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i> <span>Cancel upload</span>
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="files" id="previews">
<div id="template" class="file-row">
<div class="media">
<div class="media-left">
<img data-dz-thumbnail/>
</div>
<div class="media-body">
<h4 class="media-heading name" data-dz-name></h4>
<div class="col-xs-12"><strong class="error text-danger" data-dz-errormessage></strong></div>
<div class="col-xs-12">
<div class="col-sm-3">
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</div>
<div class="col-sm-9 text-right">
<button class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Portfolio</div>
<div class="panel-body">
<div class="row">
@foreach($photos as $photo)
<div class="col-xs-6 col-md-3">
<a href="#" class="thumbnail">
<img src="..." alt="...">
</a>
</div>
@endforeach
</div>
</div>
</div>
</div>
</div>@endsection
@push('styles')
<link href="{{asset('css/vendor/dropzone.css')}}"/>
@endpush
@push('scripts')
<script src="{{asset('js/vendor/dropzone.js')}}"></script>
<script src="{{asset('js/vendor/initialize/dropzone.cfg.js')}}"></script>
@endpush
所以现在我想知道这个问题是否与未定义的 MIME 类型有关,从而导致存储方法无法工作。还是我应该去别处看看?
欢迎任何建议和想法:)
这对我来说似乎不是 dropzone.js 的问题。
该错误在后端 (laravel) 中显示 "undefined method...",因此该方法对您的对象 photo
.
查看 laravel 中的文档。 (https://laravel.com/docs/5.4/filesystem#file-uploads)
也许你可以尝试这样的事情:
foreach ($request->files as $photo) {
$path = Storage::putFile('photos', $photo);
...
已更新
在 Laravel 您访问上传的文件 using the file
method, which takes the name of the file input as a parameter. And from the Dropzonejs docs:
The uploaded files can be handled just as if there would have been a html input like this:
<input type="file" name="file" />
所以试试这个:
foreach ($request->file('file') as $photo) {
只需转储您的 $request 对象,dropzone 可能会发送 base64_encoded 个不在 $request->files 数组中的图像。
另外,你可以使用 https://github.com/bnbwebexpertise/laravel-attachments
这是处理文件非常有用的软件包。
这里的问题是 $request->files
在 Laravel 代码库中不存在。由于 Illuminate\Http\Request
class 扩展了 Symfony\Component\HttpFoundation\Request
class,files
refers to Symfony\Component\HttpFoundation\FileBag
class 确实发生了包含大量没有存储方法的 Symfony\Component\HttpFoundation\File\UploadedFile
。
简单修复:
将 $request->files
替换为 $request->allFiles()
,这应该会为您提供一个 Illuminate\Http\UploadedFile
class 数组,其中包含存储方法
如果您需要进一步的帮助,请随时在评论部分提出任何问题
我有一个类似的问题,但在我的例子中,只是没有 enctype="multipart/form-data"
属性 包含在 <form>
标签中。一旦我这样做了,它就奏效了。而且我看到你也没有 <form>
标签。
<form action="/route" method="post" enctype="multipart/form-data">
<!-- your code for dropzone goes here -->
</form>
另外,在 AdminController
控制器的 portfolioStore()
方法中,
foreach ($request->allFiles() as $photo) {
$filename = $photo->store('photos');
$test = PortfolioPhoto::create([
'filename' => $filename,
'title' => 'title',
'alt' => 'alt'
]);
}
请不要这样做!
您在此处创建的插入查询过多。
重构如下。你可以摆脱一个数据库查询:)
$photos = [];
foreach ($request->files as $photo) {
$filename = $photo->store('photos');
$photos[] = [
'filename' => $filename,
'title' => 'title',
'alt' => 'alt'
];
}
PortfolioPhoto::createMany($photos);
并且在之前的 post 中,我回答了如何方便地在 Laravel 中存储文件。你可以$filename = $photo->store('photos');
部分。
希望这对您有所帮助:)