<?php | |
namespace Craft; | |
class Plugin_FileController extends BaseController | |
{ | |
protected $valid_extensions = array('jpg', 'jpeg', 'png', 'pdf'); | |
protected $assetSourceId = 1; | |
public function actionUpload() | |
{ | |
$this->requireAjaxRequest(); | |
$errors = array(); | |
$success = array(); | |
foreach ($_FILES['files']['error'] as $key => $error) | |
{ | |
if (!$error) | |
{ | |
$filename = $_FILES['files']['name'][$key]; | |
$file = $_FILES['files']['tmp_name'][$key]; | |
$extension = end(explode('.', $filename)); | |
if (!in_array($extension, $this->valid_extensions)) | |
{ | |
$errors[] = "$filename has an invalid extension."; | |
continue; | |
} | |
$uploadDir = craft()->assetSources->getSourceById($this->assetSourceId)->settings['path']; | |
if (move_uploaded_file($file, $uploadDir . $filename)) | |
{ | |
IOHelper::deleteFile($file); | |
$file = $uploadDir . $filename; | |
$fileModel = new AssetFileModel(); | |
$fileModel->sourceId = $this->assetSourceId; | |
$fileModel->folderId = $this->assetFolderId; | |
$fileModel->filename = IOHelper::getFileName($filename); | |
$fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename)); | |
$fileModel->size = filesize($file); | |
$fileModel->dateModified = IOHelper::getLastTimeModified($file); | |
craft()->assets->storeFile($fileModel); | |
$success[] = "$filename was saved."; | |
} | |
else | |
{ | |
$errors[] = "$filename was unable to be saved."; | |
continue; | |
} | |
} | |
} | |
$this->returnJSON(compact('errors', 'success')); | |
} | |
} |
<form method="post" action="" accept-charset="UTF-8" enctype="multipart/form-data"> | |
<input type="hidden" name="action" value="plugin/file/upload" /> | |
<input type="hidden" name="redirect" value="" /> | |
<p><input type="file" name="file" multiple></p> | |
<input type="submit" class="btn submit" value="Upload"> | |
</form> | |
<div style="margin-top:20px" id="output" /> | |
{% set js %} | |
$(function() { | |
$("form").submit(function() { | |
var url = '/admin/actions/' + $(this).children("[name=action]").attr('value'), | |
files = $(this).find("[name=file]")[0].files, | |
formdata = new FormData(), | |
file, | |
reader; | |
for (var i = 0; i < files.length; i++) { | |
file = files[i]; | |
if (window.FileReader) { | |
reader = new FileReader(); | |
reader.readAsDataURL(file); | |
} | |
formdata.append("files[]", file); | |
} | |
$("#output").html("Uploading..."); | |
$.ajax({ | |
type: "POST", | |
url: url, | |
data: formdata, | |
processData: false, | |
contentType: false, | |
success: function(json) { | |
window.json = json; | |
console.log(json); | |
var errors = json['errors'], | |
success = json['success'], | |
html = "<p><b>" + errors.length + " errors, " + success.length + " successfully uploaded</b></p>"; | |
$("#output").html(html); | |
}, | |
error: function (xhr, ajaxOptions, thrownError) { | |
alert("ERROR: " + xhr.status + " " + thrownError); | |
} | |
}); | |
return false; | |
}); | |
}) | |
{% endset %} | |
{% includeJs js %} |
Thanks a lot for this! Great starting point to get things going.
Great..!!!
In the HTML, I ran into one problem:
I had to use square brackets in the name attribute of the file upload input element, like:
<input type="file" name="file[]" multiple>
In the PHP, there are three things that were causing issues for me:
The $_FILES superglobal was not indexed by 'files', but rather 'file', even with multi-uploads:
$_FILES['file']['name'][$key];
Additional, the end() function only accepts an argument passed by reference. It has to be a real variable and cannot be the return of a function. Simply assign the output of explode() to a variable then pass the variable, like this:
$filenamePieces = explode('.', $filename);
$extension = end($filenamePieces);
Lastly, the function to grab the asset base path was returning the literal "{basePath}/path/to/assets" string with the curly braces and all. The placeholder was not replaced. Having set up my config environment variables exactly according to the docs, to fix this, I used this code:
$uploadDir = craft()->assetSources->getSourceById($this->uploadAssetSourceId)->settings['path'];
$uploadDir = str_replace('{basePath}', craft()->config->get('environmentVariables')['basePath'], $uploadDir);
Hopefully, this helps someone down the road!
@MFFunmaker I tried to implement it according to your changes, however i am running into ERROR: 500 Internal Server Error
this is the form (it throws a syntax error if i change the name to file[]):
<form class="upload" method="POST" enctype="multipart/form-data">
<input type="hidden" name="action" value="assetLinks/upload/UploadFile">
{{ getCsrfInput() }}
<input class="file btn" type="file" name="file" multiple>
<button data-icon="upload" class="uploadfile btn submit" type="submit">Upload file</button>
</form>
this is the controller:
<?php
namespace Craft;
class AssetLinks_UploadController extends BaseController
{
protected $valid_extensions = array('jpg', 'jpeg', 'png', 'pdf');
protected $assetSourceId = 1;
public function actionUploadFile()
{
$this->requireAjaxRequest();
$errors = array();
$success = array();
foreach ($_FILES['files']['error'] as $key => $error)
{
if (!$error)
{
$filename = $_FILES['files']['name'][$key];
$file = $_FILES['files']['tmp_name'][$key];
$filenamePieces = explode('.', $filename);
$extension = end($filenamePieces);
if (!in_array($extension, $this->valid_extensions))
{
$errors[] = "$filename has an invalid extension.";
continue;
}
$uploadDir = craft()->assetSources->getSourceById($this->uploadAssetSourceId)->settings['path'];
$uploadDir = str_replace('{basePath}', craft()->config->get('environmentVariables')['basePath'], $uploadDir);
if (move_uploaded_file($file, $uploadDir . $filename))
{
IOHelper::deleteFile($file);
$file = $uploadDir . $filename;
$fileModel = new AssetFileModel();
$fileModel->sourceId = $this->assetSourceId;
$fileModel->folderId = $this->assetFolderId;
$fileModel->filename = IOHelper::getFileName($filename);
$fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename));
$fileModel->size = filesize($file);
$fileModel->dateModified = IOHelper::getLastTimeModified($file);
craft()->assets->storeFile($fileModel);
$success[] = "$filename was saved.";
}
else
{
$errors[] = "$filename was unable to be saved.";
continue;
}
}
}
$this->returnJSON(compact('errors', 'success'));
}
}
Hello,
$this->requireAjaxRequest();
This is defined any where or It is Craft by default function. How I can use in Craft 3. Can you please guide me for this?
$this->assetFolderId
...assetFolderId
is not being defined like you have definedassetSourceId