I have been messing around with Blueimp's Jquery File Upload for a couple weeks on PHP and I am encountering some issues. I am teaching myself how to program in PHP so I am still getting acclimated to how things work, so apologies for any confusion and I will attempt to clarify as best I can.
I need user uploads to be inserted into their specific username folders in the upload destination directory. I have followed the numerous writeups, answers and faqs for turning on said user directories (for this plugin) and at best, a folder is created for the session with a string of misc. characters, but all uploads regardless of the username go to the same folder, not the users' respective folder. Is it possible to tell the script to read and use the specific username/id/etc as a variable? I'm pretty sure it is, but currently I cannot find a clear-cut method. I have tried to keep my code as basic and similar to the released Blueimp versions for the sake of clarity.
So, here goes.
**Working:**User registers, info is inserted into database, a respective username folder is automatically created inside the upload directory and waits patiently to be filled with delicious files.
**Not working:**Upload script is not reading the username/variable to be used as the target folder name. When executed, "Error SyntaxError: Unexpected token <" is returned, and inserts the uploaded file into the parent "/uploads/" folder.
index.php (inside the original server/php/ directory)
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
$upload_handler = new UploadHandler();
UploadHandler.php
function __construct($options = null, $initialize = true, $error_messages = null) {
$this->response = array();
$this->options = array(
'script_url' => $this->get_full_url().'/'.basename($this->get_server_var('SCRIPT_NAME')),
'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/../../uploads/'.$username.'/',
'upload_url' => $this->get_full_url().'/../../uploads/'.$username.'/',
'user_dirs' => false,
'mkdir_mode' => 0755,
'param_name' => 'files',
My understanding is that the $username variable needs to be defined, but where and how is where I'm lost. I can have the page call and print the username, id, email, and pretty much anything else -on- the page, but the variable/token is not translating into the upload directory script.
Thanks in advance for any input.
You will need to edit your index.php to set the $username variable.
Update the code to this:
require('UploadHandler.php');
$upload_handler = new UploadHandler($username);
In the UploadHandler.php file, update the __construct to this:
function __construct($username, $options = null, $initialize = true, $error_messages = null) {
It should now capture the $username being passed through.
You can try to restore the original server/php/UploadHandler.php then follow this article in the wiki:
jQuery-File-Upload wiki - PHP-user-directories
"To provide your own implementation, you can override the get_user_id method"
edit your index.php:
<?php
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
class CustomUploadHandler extends UploadHandler {
protected function get_user_id() {
return $_REQUEST['username'];
}
protected function set_additional_file_properties($file) {
$file->deleteUrl = $this->options['script_url']
.$this->get_query_separator($this->options['script_url'])
.$this->get_singular_param_name()
.'='.rawurlencode($file->name)
.'&username='.$_REQUEST['username']
;
$file->deleteType = $this->options['delete_type'];
if ($file->deleteType !== 'DELETE') {
$file->deleteUrl .= '&_method=DELETE';
}
if ($this->options['access_control_allow_credentials']) {
$file->deleteWithCredentials = true;
}
}
}
$upload_handler = new CustomUploadHandler(array(
'user_dirs' => true,
));
and main.js
$(function () {
'use strict';
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: 'server/php/index.php?username=' + username,
});
// Enable iframe cross-domain access via redirect option:
$('#fileupload').fileupload(
'option',
'redirect',
window.location.href.replace(
/\/[^\/]*$/,
'/cors/result.html?%s'
)
);
// Load existing files:
$('#fileupload').addClass('fileupload-processing');
$.ajax({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: $('#fileupload').fileupload('option', 'url'),
dataType: 'json',
context: $('#fileupload')[0]
}).always(function () {
$(this).removeClass('fileupload-processing');
}).done(function (result) {
$(this).fileupload('option', 'done')
.call(this, $.Event('done'), {result: result});
});
});
}
Related
I want to delete files from server which have been uploaded through Dropzone.But,Only thumbnails have been deleted.File in the server not erased.I have got an error in console.http://localhost:8000/upload/delete 500 (Internal Server Error)'
My Upload Method In Controller
public function upload(Request $request){
$file= $request->file('file');
$filename=$file->getClientOriginalName();
$upload='uploads/topics';
$file->move($upload, $filename);
}
Dropzone Script file.
Dropzone.options.addImages = {
maxFilesize: 8,
addRemoveLinks: true,
dictRemoveFile: 'Remove',
init:function() {
this.on("removedfile", function(file) {
$.ajax({
type: 'POST',
url: 'upload/delete',
data: {id: file.name},
dataType: 'html',
success: function(data){
var rep = JSON.parse(data);
}
});
} );
},
}
My delete method in controller.
public function delete(Request $request){
$filename = $request->input('id');
unlink('uploads/topics'.$filename);
}
Two issues that I can see right away:
In your delete controller method you are trying to access $request but you haven't injected it.
The request input method is lowercase.
I believe this is closer to what you need:
public function delete(Request $request){
$filename = $request->input('id');
unlink('uploads/topics/' . $filename);
}
Some notes:
Whenever you get an "internal server error" that means you need to check your error logs. There are details in one of your log files that will tell you the exact error.
Right now your delete method could allow a user to delete things you may not want them to delete. I could easily post a filename to that endpoint and delete anything from your topics folder.
Even more dangerous, this code appears to be at risk for a traversal attack. See here for details: https://www.owasp.org/index.php/Path_Traversal
I have a page that manages uploads in specific folders. On this page, there is a upload form for each folder. So, here is my javascript file (main.js), each form has the ".fileupload" class :
$(function () {
'use strict';
$('.fileupload').fileupload();
$('.fileupload').addClass('fileupload-processing');
$.ajax({
url: $('.fileupload').fileupload('option', 'url'),
dataType: 'json',
context: $('.fileupload')[0]
}).always(function () {
$(this).removeClass('fileupload-processing');
}).done(function (result) {
$(this).fileupload('option', 'done')
.call(this, $.Event('done'), {result: result});
});
});
To tell the script to catch and upload files in specific folder, I add a variable called "folder" in the action path that I will get in my index.php upload script. Here is my HTML :
<form class="fileupload" action="//mywebsite.com/server/php/index.php?folder=<?=$folder?>" method="POST" enctype="multipart/form-data">
...
</form>
Here is my PHP (server/php/index.php) :
require('UploadHandler.php');
$upload_handler = new UploadHandler(array(
'upload_dir' => "/home/mywebsite/public_html/users/" . $_GET['folder'],
'upload_url' => "//mywebsite.com/users/" . $_GET['folder']
));
The problem is that it doesn't seem to work. I mean, images located in each folder are not shown and the upload doesn't start anyway.
My question is how to force (through my HTML/PHP) the upload script path with specific variable (here "folder") encapsulated?
I'm not quite sure what <?=$folder?> does but I suspect that's the problem. Why not generate the action link dynamically in your JS function? Something like:
var folder = 'folder1'; //<-- insert folder name here
var actionlink = '//mywebsite.com/server/php/index.php?folder=' + folder;
$('.fileupload').attr('action', actionlink);
Hi all: I have another challenge:
Im using Jquery fileuploader for php from blueimp: https://github.com/blueimp/jQuery-File-Upload
I'm modifying the code to implement the uploader in my web.
I can use it correctly, but the documentation is poor about certain adds or mods:
I'm trying to modify the file UploaderHandler.php to create a folder with the username(unique), but I don't know WHERE to put my mkdir() function...
And want to upload the files changing the names to 1.txt,2.pdf,3.doc...etc,etc,etc
Any help?
PD: I'm thinking about 3 solutions:
1) put my mkdir() function in the login.php, and when the user logs in, it check the folder exists and it's empty... and each time he reloads certain .php files. Not the best solution, I guess.
2) put mkdir() function in get_upload_path from uploadHandler.php
3) put my rename() function in get_unique_filename from uploadHandler.php
EDIT: I just tryied the 2) option: I modified the UploadHandler.php.
It works, create the folder with username, and put the uploaded file in the folder. But in the AJAX I don't receive response, and don't create the response line:
UploadHandler.php:
function __construct($options = null, $initialize = true, $error_messages = null){
ob_start();
include('../conexion.php');
include('../session/session.php');
$url_subida = dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$usuario.'/';
if(!is_dir($url_subida)){
mkdir($url_subida, 0777);
}
else{
error_log($url_subida);
}
$this->options = array(
'script_url' => $this->get_full_url().'/',
'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$usuario.'/',
'upload_url' => $this->get_full_url().'/'.$usuario.'/',
[...]
Response in AJAX in the HTML/php:
$(function(){
$('#fileupload').fileupload({
dataType: 'json',
done: function (e, data){
$.each(data.result.files, function (index, file) {
numarch++;
$('<div id="archivo_'+numarch+'" />').appendTo('#files');
if (file.error){
$('<img src="img/x.png" title="Error" alt="Error"/>').appendTo('#archivo_'+numarch);
$('<p class="text-danger"/>').text(file.error).appendTo('#archivo_'+numarch);
}
else{
var newFileDiv = $("<img title='Archivo subido OK' alt='Archivo subido OK'/>
<p>"+file.name+"</p>
<div id='borrarDiv' name='borrarDiv' class='btn btn-danger delete' onclick= borrar_archivo ('archivo_"+numarch+"','"+file.deleteUrl+"','"+file.deleteType+"','"+numarch+"')>
<i class='glyphicon glyphicon-trash'></i>
<span>Borrar</span></div>");
$('#archivo_'+numarch).append(newFileDiv);
}
});
},
progressall: function (e, data){
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').html(progress + '%');
$('#progress .progress-bar').css('width',progress + '%');
}
});
});
Could you help me to get the response?
Ok, challenge completed:
First: how to upload files to a custom URL, changed by the name of the user:
In the implementation of jQuery Fileupload of BlueImp, you must use 2 files to control the uploads: index.php and uploadhandler.php.
The first creates the object:
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
$upload_handler = new UploadHandler();
You must change it to:
ob_start(); //get session
//include files to operate with database and session
include("../conection.php");
include("../session/session.php");
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
//add var $options. It is an array, you can see it in uploadhandler.php, in the constructor
//you modify the data: the upload_dir and the upload_url
$options = array('upload_dir'=>$usuario.'/', 'upload_url'=>$usuario.'/');
//then add the array to the constructor declaration
$upload_handler = new UploadHandler($options);
With this modification you can send to the constructor the variable upload path.
I hope this help you all.
EDIT: PROBLEM WITH WHITE SPACES
To fight the filename white spaces you must change this function:
protected function get_unique_filename($file_path, $name, $size, $type, $error, $index, $content_range){
while(is_dir($this->get_upload_path($name))){
$name = $this->upcount_name($name);
}
// Keep an existing filename if this is part of a chunked upload:
$uploaded_bytes = $this->fix_integer_overflow(intval($content_range[1]));
while(is_file($this->get_upload_path($name))){
if ($uploaded_bytes === $this->get_file_size($this->get_upload_path($name))){
break;
}
$name = $this->upcount_name($name);
}
//converts the white spaces in _
$name= str_replace(" ", "_", $name);
return $name;
}
I am using JQuery File Upload plugin to make add the possibility to upload files to my website.
The upload script is in a page like "index.php?cartella_id=x" (x is a number that indicated a album ID).
I would like to store files like this:
server/php/files
- directory 1/
- - Image x
- - Image y
- directory 2/
- - Image z
- - Image z(2)
I basically want to create a different directory for each album.
Storing the images like I want is not hard because I pass $cartella_id by using a hidden input in the form like this
<input type="hidden" name="cartella_id" value="<?php echo $cartella_id; ?>">
In the server/php/index.php file I check if the user is logged in and if the album exists like this
session_start();
if(!isset($_SESSION["username"])) {
die();
}
if(isset($_REQUEST["cartella_id"])) {
$cartella_id = (int) $_REQUEST["cartella_id"];
$sql = "SELECT * FROM cartelle WHERE cartella_id = $cartella_id";
$query = mysql_query($sql);
if($cartella = mysql_fetch_array($query)) {
$upload_dir = '/files/'.$cartella_id.'/';
} else {
die();
}
} else {
die();
}
And in the UploadHandler.php page I edit the 'upload_dir' and 'upload_url' options.
'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/'.$_REQUEST["cartella_id"].'/',
'upload_url' => $this->get_full_url().'/files/'.$_REQUEST["cartella_id"].'/',
Upload works fine... the problem is that if I refresh the upload page I can't see already-uploaded files like the script would show me when no custom path is specified. I can use $_SESSION to fix this problem but I don't like this solution and the Delete buttons wouldn't work in any case.
I studied the PHP code a lot and I've also googled a lot but I couldn't find a solution that works for me.
How do I send custom variables when the script is checking for existing files (I couldn't find that piece of code)?
How do I make the Delete buttons work?
Thanks in advance
So I solved the first problem (make files visible even after reloading the page) by editing js/main.js.
I edited this:
url: $('#fileupload').fileupload('option', 'url'),
to this
url: ($('#fileupload').fileupload('option', 'url') + "?cartella_id="+ document.getElementById('cartella_id').value),
Still have to make the delete buttons work though.
I had the same problem and i solved it enabling the user-directories and overriding the methods in the class UploadHandler as suggested here:
jQuery-File-Upload PHP-user-directories
I added an extra parameter to the delete url.
My index.php :
<?php
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
class CustomUploadHandler extends UploadHandler {
protected function get_user_id() {
return $_REQUEST['recordId'];
}
protected function set_additional_file_properties($file) {
$file->deleteUrl = $this->options['script_url']
.$this->get_query_separator($this->options['script_url'])
.$this->get_singular_param_name()
.'='.rawurlencode($file->name)
.'&recordId='.$_REQUEST['recordId']
;
$file->deleteType = $this->options['delete_type'];
if ($file->deleteType !== 'DELETE') {
$file->deleteUrl .= '&_method=DELETE';
}
if ($this->options['access_control_allow_credentials']) {
$file->deleteWithCredentials = true;
}
}
}
$upload_handler = new CustomUploadHandler(array(
'user_dirs' => true,
));
and i changed the url in
my main.js:
$(function () {
'use strict';
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: 'server/php/index.php?recordId=' + recordId,
});
// Enable iframe cross-domain access via redirect option:
$('#fileupload').fileupload(
'option',
'redirect',
window.location.href.replace(
/\/[^\/]*$/,
'/cors/result.html?%s'
)
);
// Load existing files:
$('#fileupload').addClass('fileupload-processing');
$.ajax({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: $('#fileupload').fileupload('option', 'url'),
dataType: 'json',
context: $('#fileupload')[0]
}).always(function () {
$(this).removeClass('fileupload-processing');
}).done(function (result) {
$(this).fileupload('option', 'done')
.call(this, $.Event('done'), {result: result});
});
});
}
i have not edited the UploadHandler.php
I get the feeling I'm missing something terribly obvious with this, so I'm hoping someone can point me in the right direction. This question specifically pertains to the jQuery file upload script found http://blueimp.github.com/jQuery-File-Upload/
I loaded this very nice and handy set of files on my server and it worked great out of the box. I'd like to enable dynamically creating user directories for users to upload files, and I've followed the directions given here: https://github.com/blueimp/jQuery-File-Upload/wiki/PHP-user-directories
I've opened up the server/php/index.php file, which contains these lines:
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
$upload_handler = new UploadHandler();
and I've edited the file to read as follows:
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
require('upload.class.php');
class CustomUploadHandler extends UploadHandler {
protected function get_user_id() {
$userid = 99771;
return $userid;
}
}
$upload_handler = new CustomUploadHandler(array(
'user_dirs' => true
));
Obviously since this isn't live yet, I'm testing with a static user id (tested with and without quotes), but I don't see how this makes a difference. When I try running this, I get the error:
SyntaxError: JSON.parse: unexpected character
What could this be from? I've also tried putting the inherited class in the UploadHandler.php file instead, but I get the same error message.
http://gloryplus.com/index.php?route=product/product&path=82&product_id=172
for ( ; i < len; i++ ) {
file = this.files[i];
if (!!file.type.match(/image.*/)) {
if ( window.FileReader ) {
reader = new FileReader();
reader.onloadend = function (e) {
showUploadedItem(e.target.result, file.fileName);
};
reader.readAsDataURL(file);
}
if (formdata) {
formdata.append("images[]", file);
}
}
}
if (formdata) {
$.ajax({
url: "upload.php",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function (res) {
document.getElementById("response").innerHTML = res;
}
});
}