I use Dropzone image uploader. This plugin fortunately uploaded my images in binary format and I like it. And also move file uploaded in my "/upload" folder perfectly but without extension. I need to show the image uploaded, from upload folder in my HTML page by different extension. This is a screenshot of my upload folder:
How can I read and show the images by their address in tag?
The upload folder is 2 previews directory from my HTML file. How can I address in ?
This is my HTML uploader:
<meta name="csrf-token" content="XYZ123">
<form id="upload-widget" method="post" action="/upload" class="dropzone">
<div class="fallback">
<input name="file" type="file" />
</div>
</form>
This is my Dropzone uploader js code:
Dropzone.options.uploadWidget = {
paramName: 'file',
maxFilesize: 2, // MB
maxFiles: 1,
dictDefaultMessage: 'Drag an image here to upload, or click to select one',
headers: {
'x-csrf-token': document.querySelectorAll('meta[name=csrf-token]')[0].getAttributeNode('content').value,
},
acceptedFiles: 'image/*',
init: function() {
this.on('success', function( file, resp ){
console.log( file );
console.log( resp );
});
this.on('thumbnail', function(file) {
if ( file.width < 20 || file.height < 20 ) {
file.rejectDimensions();
} else {
file.acceptDimensions();
}
});
},
accept: function(file, done) {
file.acceptDimensions = done;
file.rejectDimensions = function() {
done('The image must be at least 20 x 20')
};
}
};
And I didn`t use my controllers for this.
Related
Im using DropzoneJS to upload Multiple files on my project.
I save the files in "wwwroot/ODIUpload" with new names using "Guid" in my "GeneratorClass" & Save the images name in OrderDetailImagesUpload Table in Database.
Now, after uploading the images, i want to if the user press delete button, the image will be deleted in "wwwroot/ODIUpload".
How can I do that?
View & Save Location Pic
View Code:
<div class="col-md-12">
<div id="dropzone ">
<form action="/Package/Design/#Model.OrderDetailID" method="post" enctype="multipart/form-data"
id="myAwesomeDropzone" class="dropzone">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="OrderDetailID"/>
<span asp-validation-for="ImageName" class="validation-error uplood-error"></span>
#Html.AntiForgeryToken()
<div></div>
<div class=" text-center">
<span class="uploadicon"> <i class="fal fa-images"></i> </span>
<div class="dz-message needsclick">
<button type="button" class="dz-button uploadicontext"> Upload Here</button><br/>
</div>
</div>
</form>
</div>
Js Code:
<script>
function myParamName() {
return "files";
}
Dropzone.options.myAwesomeDropzone = {
paramName: myParamName, // The name that will be used to transfer the file
maxFiles: 10,
dictRemoveFile: "Delete",
maxFilesize: 100,
uploadMultiple: true,
acceptedFiles: ".jpeg,.jpg,.png",
addRemoveLinks: true,
accept: function (file, done) {
if (file.name === "justinbieber.jpg") {
done("Naha, you don't.");
}
else { done(); }
},
};
</script>
Controller:
Upload Action:
[Authorize]
[Route("Package/Design/{id}")]
[HttpPost]
public IActionResult ODetailImages(OrderDetailImagesUpload _detailImagesUpload, ICollection<IFormFile> files)
{
if (files.Count() == 0)
{
ModelState.AddModelError("ImageName", "Upload Order Pics");
return View("OrderDetailImgUpload");
}
if (ModelState.IsValid)
{
_productService.AddOrderDetailImagesUpload(_detailImagesUpload.OrderDetailID, files);
return RedirectToAction("ShowBasket");
}
return View("OrderDetailImgUpload");
}
Services:
AddOrderDetailImagesUpload Service:
public void AddOrderDetailImagesUpload(int OrderDetailID, ICollection<IFormFile> imgups)
{
if (imgups != null && imgups.Any())
{
foreach (IFormFile file in imgups)
{
if (file.IsImage())
{
OrderDetailImagesUpload ODIU = new OrderDetailImagesUpload()
{
OrderDetailID = OrderDetailID,
ImageName = Generator.GetImageName() + Path.GetExtension(file.FileName)
};
_context.Add(ODIU);
string savePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/ODIUpload",
ODIU.ImageName);
using (var stream = new FileStream(savePath, FileMode.Create))
{
file.CopyTo(stream);
}
_context.SaveChanges();
}
}
}
}
I don't know how to return the names of the images to the view and assign each of them to the delete button.
I am looking to create a custom Gutenberg block with javascript that has an input that will let you upload a file of any format, and then store it in the database so I can show it on the front-end inside html a tag to be downloaded.
Here is the code inside my index.js inside my block folder (I know it is not good code. it is just for demo purposes)
wp.blocks.registerBlockType('sab/upload-block', {
title: 'Upload Block',
icon: 'lightbulb',
category: 'common',
attributes: {
url: 'string', default: '',
},
description: 'Add downloadable files to your post.',
example: { attributes: {}},
edit: function (props) {
function fileDecoder(identifier) {
const input = document.querySelector(`#${identifier}`);
const fReader = new FileReader();
fReader.readAsDataURL(input.files[0]);
fReader.onloadend = function(event) {
setAttribute({url: event.target.result})
}
}
return (
<>
<label>Upload a file</label>
<input id='upload-file' type="file" onChange={() => props.fileDecoder('upload-file')} />
</>
)
},
save: function () {
return null
}
})
And here is the code inside my index.php
<?php
/*
Plugin Name: Upload Block
Description: Add downloadable files to your post.
Version: 1.0
Author: XYZ
*/
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
// file inside my inc folder that creates the markup
require_once plugin_dir_path(__FILE__) . 'inc/generateUploadBlockHTML.php';
class UploadBlock {
function __construct() {
add_action('init', array($this, 'assets'));
}
function assets() {
register_block_type(__DIR__, array(
'render_callback' => array($this, 'theHTML')
));
}
function theHTML($attributes) {
if (isset($attributes)) {
// IDEALLY UPLOAD THE FILE HERE SO I CAN JUST USE IT ELSEWHERE, BUT I DO NOT KNOW HOW TO DO IT
return <a href="$attributes['data']['url]" download="file">
} else {
return NULL;
}
}
}
$uploadBlock = new UploadBlock();
I tried using just javascript to achieve this but I believe i need to upload the file on Wordpress database so I can use it in my other templates.
I'm using Livewire and Filepond to allow users to upload images to a gallery.
I need my users to be able to set the order of the images and save that to the database.
Filepond has an option allowReorder: true and a callback that fires when the order has been changed onreorderfiles(files, origin, target)
Here is the basics of my upload component
<div
x-data="{ 'images': null }"
x-init="
FilePond.registerPlugin(FilePondPluginImagePreview);
FilePond.registerPlugin(FilePondPluginImageExifOrientation);
FilePond.registerPlugin(FilePondPluginFileValidateType);
FilePond.registerPlugin(FilePondPluginFileValidateSize);
FilePond.registerPlugin(FilePondPluginImageResize);
FilePond.setOptions({
allowMultiple: true,
allowReorder: true,
server: {
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
#this.upload('images', file, load, error, progress)
},
revert: (filename, load) => {
#this.removeUpload('images', filename, load)
},
},
onreorderfiles(files, origin, target){
// **** What do I put here to update the order of the images in my livewire component? ******
},
});
const pond = FilePond.create($refs.input, {
acceptedFileTypes: ['image/png', 'image/jpeg'],
maxFileSize: '7MB',
allowImageCrop: true,
allowImageResize: true,
imageResizeTargetWidth: '1000px',
imageResizeTargetHeight: '1000px',
});
pond.on('addfile', (error, file) => {
if (error) {
console.log('Oh no');
return;
}
images = true;
});
"
>
<div wire:ignore wire:key="images">
<div x-show="images == null" class="ex-builder-no-images">
<i class="fas fa-image"></i>
<p>There are no images for this experience.
<br>Upload some below. <br><small>(MAX 10 Images)</small></p>
</div>
<div class="form-group text-center">
<input
id="image-upload"
type="file"
x-ref="input"
multiple
>
#error('images.*')
<p wire:key="error_images" class="mt-2 text-sm text-red-600" id="email-error">{{ $message }}</p>
#enderror
</div>
</div>
</div>
I'm also showing a preview of the first image in the gallery (this is the gallery's featured image) like this <img src="{{ $images ? $images[0]->temporaryUrl() : '/images/placeholder.jpg' }}"> I'm expecting this image to update after the user drags a new image to be the first.
How can I update the image order in the public $images = []; found in my livewire componenet using the onreoderfiles() callback?
Thanks!
Not sure if this is correct, but it seems to work
I added this to FilePond.setOptions()
FilePond.setOptions({
allowMultiple: true,
allowReorder: true,
server: {
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
#this.upload('images', file, load, error, progress)
},
revert: (filename, load) => {
#this.removeUpload('images', filename, load)
},
},
// Added this ----------------------------------------
onreorderfiles(files, origin, target){
#this.set('images', null);
files.forEach(function(file) {
#this.upload('images', file.file);
});
},
});
This removes the previous uploaded images and reuploads with the new order.
I'm trying to use dropzone in laravel project but I can't get the files in server side.
My blade html code:
{!! Form::open(['id' => 'create-intervention-form', 'url' => '/create-intervention', 'method' => 'post', 'class' => '']) !!}
<div id="multimedia" class="data new dropzone">
</div>
<div class="btn-new-bottom">
Criar Intervenção
</div>
{!! Form::close() !!}
In jquery I put this code:
$("div#multimedia").dropzone({
url: "/create-intervention",
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 1024,
autoProcessQueue: false
});
To submit the form I have a jquery function to submit. In controller I try to get $files[] = Input::file('file'); but this return null.
Controller:
public function store(Request $request)
{
$rules = array(
);
// do the validation ----------------------------------
// validate against the inputs from our form
$validator = Validator::make(Input::all(), $rules);
// check if the validator failed -----------------------
if ($validator->fails())
{
// get the error messages from the validator
$messages = $validator->messages();
return redirect()->back()->withErrors($validator)->withInput();
}
else
{
$files[] = Input::file('file');
var_dump($files);
}
};
How can I do this? I want to use dropzone to upload multiple files but just when I submit the form. In controller I have to save each file in directory and file name in database.
Thank you
Add to your form open method 'files' => true
documentation
You can try to get the files thought Request too in a loop:
Controller:
public function store(Request $request)
{
$rules = array();
// do the validation ----------------------------------
// validate against the inputs from our form
$validator = Validator::make(Input::all(), $rules);
// check if the validator failed -----------------------
if ($validator->fails())
{
// get the error messages from the validator
$messages = $validator->messages();
return redirect()->back()->withErrors($validator)->withInput();
}
else
{
foreach( $request->file('file') as $file ){
$filename = $file->store('file');
#saves the file
$array_images_names[] = $filename;
}
var_dump($files);
}
};
JavaScript (allowing to accept multiple files)
var post_url_images = $('#post_url_images').val();
Dropzone.options.frm_drop_images = {
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 1024,
// The configuration we've talked about above
url: post_url_images,
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
// The setting up of the dropzone
init: function() {
var myDropzone = this;
// First change the button to actually tell Dropzone to process the queue.
this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
// of the sending event because uploadMultiple is set to true.
this.on("sendingmultiple", function() {
// Gets triggered when the form is actually being sent.
// Hide the success button or the complete form.
});
this.on("successmultiple", function(files, response) {
// Gets triggered when the files have successfully been sent.
// Redirect user or notify of success.
});
this.on("errormultiple", function(files, response) {
// Gets triggered when there was an error sending the files.
// Maybe show form again, and notify user of error
});
}
};
Try to use your HTML form as below:
<div class="dropzone dropzone-previews" id="frm_drop_images" class="dropzone" method="post" action="{{ url('/admin/products/upload/image') }}"></div>
<!-- hiddent field to set where to post the images -->
<input type="hidden" name="post_url_images" id="post_url_images" value="{{ url('/create-intervention') }}" >
<div class="btn-new-bottom">
Criar Intervenção (Não precisa usar este botão)
</div>
I'm uploading multiple files on submission of a form.
This is the image upload input (html):
<form class="form-inline" id="cost-estimate-form">
<div class="form-field-short col s12 m6">
<i class="material-icons prefix">insert_photo</i>
<label for="input-file">Upload photos</label>
<input id="input-file" type="file" name="images" accept="image/jpeg, image/png, application/pdf" multiple/> <!-- todo: ugly on safari -->
</div>
<!-- rest-->
<button class="btn waves-effect col s6 m3 offset-m6" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
And the .js
'submit #cost-estimate-form': function(event, tmpl){
event.preventDefault();
let files;
if(event.target.images) {
files = event.target.images.files;
}
Meteor.call('travelRequests.insert', tmpl.data, function(err, trId) {
if (err) {
alertError(err.message);
}
else {
if (files) {
var imageDetails = [];
for (var i = 0, j = 0, ln = files.length; i < ln; i++) {
Image.insert(files[i], function (err, fileObj) {
if (err) {
console.log('Error uploading image: ');
console.log(err);
} else {
console.log('[DB] insert image(id=' + fileObj._id);
j++;
let imagePath = '/uploads/images-' + fileObj._id + '-' + fileObj.name();
imageDetails.push({id: fileObj._id, name: fileObj.name(), path: imagePath});
if (j === ln) { // when last file is successful
Meteor.call('travel.addImages', trId, imageDetails,
function (err, _) {
if (err) alertError(err.reason);
});
console.log('travel.addImages');
}
}
});
}
}
}
});
Router.go('travel_requests_list');
Meteor.call('travelRequests.insert'... creates an entity. Then I try to update the images uploaded for that entity after uploading the files with Meteor.call('travel.addImages',....
However, when clicking submit button on the form, the next screen refreshes multiple times and I get error in client:
cfs_power-queue.js:525 Error: "Queue" network [undefined], Error
at cfs_upload-http.js:382
at cfs_upload-http.js:108
at underscore.js:794
at XMLHttpRequest.xhr.onreadystatechange (cfs_upload-http.js:167)
And in the mongodb, some files are completely uploaded and some are not:
Example complete file:
{
"_id" : "MEWTZaXLX9gvx5utc",
"original" : {
"name" : "IMG_3867.JPG",
"updatedAt" : ISODate("2017-07-19T02:57:55Z"),
"size" : 4231984,
"type" : "image/jpeg"
},
"uploadedAt" : ISODate("2017-09-15T02:30:40.204Z"),
"copies" : {
"images" : {
"name" : "IMG_3867.JPG",
"type" : "image/jpeg",
"size" : 4231984,
"key" : "images-MEWTZaXLX9gvx5utc-IMG_3867.JPG",
"updatedAt" : ISODate("2017-09-15T02:30:40Z"),
"createdAt" : ISODate("2017-09-15T02:30:40Z")
}
}
}
Example incomplete file:
{
"_id" : "cgHcSCRPvzgekW6Ai",
"original" : {
"name" : "IMG_3869.JPG",
"updatedAt" : ISODate("2017-07-19T02:58:10Z"),
"size" : 4108047,
"type" : "image/jpeg"
},
"chunkSize" : 2097152,
"chunkCount" : 1,
"chunkSum" : 2
}
Collection definition:
Image = new FS.Collection("images", {
/* the file director: .meteor/local/uploads */
stores:[new FS.Store.FileSystem("images",{path:Meteor.settings.uploadRoot+"/uploads"})],
filter: {
allow: {
contentTypes: ['image/*', 'application/pdf'] //allow only images and pdf in this FS.Collection
}
}
});
if(Meteor.isServer){
Image.allow({
'insert': function () {
return true;
},
'update': function () {
return true;
},
'download':function(){
return true;
}
});
}
Why does this happen? Should I wait for file upload to finish before routing to the next screen? How do I do that if that is the problem?
I'm new to meteor so any help is appreciated.
As you are not using kadira's FlowRouter, I may be not be the right person to answer about the redirection issues as Router mechanism can hold data inside routes as well which is very bad. As per latest Meteor conventions, Subscription must be at template level implementation.
But, I can tell you that you can wait for completion of image upload. When the image is uploaded successfully only then you can perform next operation which can be either redirection to next page or any other operation.
Below is the code to wait for the completion of your image upload. The basic Idea is the url of image is generated only when the Image gets uploaded completely. so we wait for url to be generated, Once we receive url, it means we are done.
var myImage = event.target.images.files[0];
if(myImage){
var myFile = new FS.File(myImage);
Images.insert(myFile, function(err, result){
if(!err){
var liveQuery = Images.find(result._id).observe({
changed: function(newImage, oldImage) {
if (newImage.url() != null) {
liveQuery.stop();
// Here the image is uploaded successfully.
}
}
});
} else {
//console.log(err);
}
});
}