MODX - user profile photo upload - modx

I am trying to allow users to upload photos to their profiles. I am sure I am doing something wrong...
What I currently have configured:
Update Profile Form
[[!UpdateProfile? &useExtended=`1` &preHooks=`user_profile_image` &postHooks=`redirect_profile_update`]]
<div class="update-profile">
<div class="updprof-error">[[+error.message]]</div>
[[+login.update_success:if=`[[+login.update_success]]`:is=`1`:then=`[[%login.profile_updated? &namespace=`login` &topic=`updateprofile`]]`]]
<form class="form" enctype="multipart/form-data" action="[[~[[*id]]]]" method="post">
<input type="hidden" name="nospam:blank" value="" />
<label for="fullname"><i class="icon-user"></i> <strong>[[!%login.fullname? &namespace=`login` &topic=`updateprofile`]]</strong>
<span class="error">[[+error.fullname]]</span>
</label>
<input type="text" name="fullname" id="fullname" value="[[+fullname]]" />
<label for="email"><i class="icon-envelope"></i> <strong>[[!%login.email]]</strong>
<span class="error">[[+error.email]]</span>
</label>
<input type="text" name="email:required:email" id="email" value="[[+email]]" />
<label for="test_field">Test Field
<span class="error">[[+error.custom_field]]</span>
</label>
<input type="text" name="test_field" id="test_field" value="[[+test_field]]" /><br/>
<div class="row clearfix">
<div class="label">Photo<span class="error">[[+fi.error.nomination_file]]</span></div>
<div class="input"><input id="nomination_file" name="nomination_file:required" type="file" value="[[+fi.nomination_file]]" maxlength="100000" /></div>
</div>
<br class="clear" />
<button class="btn-info btn btn-large" type="submit" name="login-updprof-btn">Update Profile</button>
</form>
</div>
User_profile_image snippet
<?php
// initialize output;
$output = true;
// get the current user name to create the file name as
$userName = $modx->user->get('username');
// valid extensions
$ext_array = array(`jpg', 'jpeg', 'gif', 'png');
// create unique path for this form submission
$uploadpath = 'assets/uploads/';
// you can create some logic to automatically
// generate some type of folder structure here.
// the path that you specify will automatically
// be created by the script if it doesn't already
// exist.
// EXAMPLE:
// this would put all file uploads into a new,
// unique folder every day.
// $uploadpath = 'assets/'uploads/'.date('Y-m-d').'/';
// get full path to unique folder
$target_path = $modx->config['base_path'] . $uploadpath;
// get uploaded file names:
$submittedfiles = array_keys($_FILES);
// loop through files
foreach ($submittedfiles as $sf) {
// Get Filename and make sure its good.
$filename = basename( $_FILES[$sf]['name'] );
// Get file's extension
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$ext = mb_strtolower($ext); // case insensitive
// is the file name empty (no file uploaded)
if($filename != '') {
// is this the right type of file?
if(in_array($ext, $ext_array)) {
//create file called the user name + pic
$filename = $userName . "pic".'.'.$ext ;
// full path to new file
$myTarget = $target_path . $filename;
// create directory to move file into if it doesn't exist
mkdir($target_path, 0755, true);
// is the file moved to the proper folder successfully?
if(move_uploaded_file($_FILES[$sf]['tmp_name'], $myTarget)) {
// set a new placeholder with the new full path (if you need it in subsequent hooks)
$modx->setPlaceholder('fi.'.$sf.'_new', $myTarget);
// set the permissions on the file
if (!chmod($myTarget, 0644)) { /*some debug function*/ }
} else {
// File not uploaded
$errorMsg = 'There was a problem uploading the file.';
$hook->addError($sf, $errorMsg);
$output = false; // generate submission error
}
} else {
// File type not allowed
$errorMsg = 'Type of file not allowed.';
$hook->addError($sf, $errorMsg);
$output = false; // generate submission error
}
// if no file, don't error, but return blank
} else {
$hook->setValue($sf, '');
}
}
return $output;

1) fix quote in this line
$ext_array = array(`jpg', 'jpeg', 'gif', 'png');
2) remove all :required in name fields.
3) instead
$modx->setPlaceholder('fi.'.$sf.'_new', $myTarget);
type
$hook->setValue($sf, $uploadpath . $filename);
4) after mkdir($target_path, 0755, true); add
if(file_exists($myTarget) {
chmod($myTarget,0755); //Change the file permissions if allowed
unlink($myTarget); //remove the file
}

For anyone who references this post:
move user_profile_image back to the prehooks like this:
&preHooks=`user_profile_image`
and at line 59 add the missing ")" like this:
if(file_exists($myTarget)) {

Related

Upload multiple Files in angular node multer

I am facing problem while uploading multiple files in angular, node, multer.
Last file in array is uploaded to server.
Here is my HTML.
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="Anti Black List" id="4" #fileDataAntiBlackList (onFileSelected)="onFileSelected($event ,fileDataAntiBlackList)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="Shop Act" id="3" #fileDataShopAct (onFileSelected)="onFileSelected($event ,fileDataShopAct)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="Professional Tax" id="2" #fileDataPRO (onFileSelected)="onFileSelected($event ,fileDataPRO)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<div class="mb-1">
<p class="text-muted m-0">Anti Black List</p>
<input type="file" (change)="fileChangeEvent($event)" name="GST Copy" id="1" #fileDataGST (onFileSelected)="onFileSelected($event ,fileDataGST)" ng2FileSelect [uploader]="uploader" accept="application/pdf"/>
</div>
<mat-label>First name</mat-label>
<input formControlName="f_name" matInput type="text" name="first_name" placeholder="First name" required/>
<mat-label>Last name</mat-label>
<input formControlName="l_name" matInput type="text" name="Last_name" placeholder="Last name" required/>
<button mat-raised-button color="primary" class="mx-4" (click)="onSubmit()"
[disabled]="uploader.getNotUploadedItems().length && signupForm.invalid">Upload And Save </button>
There are more fields, but i have shown less here.
Following is TS file code
filesToUpload: Array<File> = [];
fileChangeEvent(fileInput: any) {
this.filesToUpload = <Array<File>>fileInput.target.files;
//this.product.photo = fileInput.target.files[0]['name'];
}
onSubmit() {
//let files = this.getFiles();
let dbId: number;
let formData = new FormData();
const files: Array<File> = this.filesToUpload;
for(let i = 0; i < files.length;i++){
formData.append("files", files[i], files[i]['name']);
}
formData.append('first_name',this.signupForm.value.f_name);
this.http.post('http://localhost:3000/api/newUpload', formData)
.map(files => files)
.subscribe(files => console.log('files', files));
return false;
}
This is my backend API
Upload
let user_storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, DIR);
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + '' + path.extname(file.originalname));
}
});
let upload = multer({ storage: user_storage }).array('files',10);
API function
router.post('/newUpload',function(req,res){
console.log('before upload',req.body);
upload(req,res,function(err) {
//console.log(req.body);
//console.log(req.files);
if(err) {
return res.end("Error uploading file.");
}
console.log('files', req.files);
console.log(req.body);
res.send(req.files);
//res.end("File is uploaded");
});
});
This is what i have tried. Only last file in array is save in uploads folder.
Also i want to insert first name , last name etc to database but when i console req.body is gives empty json {}
Edit quetion
i got where i am missing.
Its in angular code : when i print
const files: Array<File> = this.filesToUpload;
i get last file which i uploaded. means it takes last file which is uploaded not all files.
so i use following function
getFiles(){
return this.uploader.queue.map((fileItem) => {
return fileItem.file;
});
}
So in onsubmit function
onSubmit() {
let files = this.getFiles();
let formData = new FormData();
for(let i = 0; i < files.length;i++){
console.log(files[i]);
formData.append("files", files[i],files[i]['name']);
}
When i console files[i], get all files.
But in line formData.append line i get following error
Argument of type 'FileLikeObject' is not assignable to parameter of type 'string | Blob'.
Property 'slice' is missing in type 'FileLikeObject' but required in type 'Blob
P.S : when i send file name in formdata.append, i get all file names in node serevr.
After trying different solutions, finally i got working solutions by which multiple files and other input fields are also send to sever.
In my Edit part of question, i have use following function
getFiles(){
return this.uploader.queue.map((fileItem) => {
return fileItem.file;
});
}
above code was giving error. I have just changed return line.
from
return fileItem.file;
to
return fileItem.file.rawFile;
Thats it. All remaining code is same as in edit.
you forget to add multer middleware to your router.post
it should be
outer.post('/newUpload',
upload.array('myFiles', 12),
function(req,res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
res.send(req.files);
//res.end("File is uploaded");
});
});

I can't upload file in adonis js, move is not function

I have the following file type field
<form action = "javascript:;" enctype="multipart/form-data" id="formulario" class="form-horizontal">
<div class="form-group">
<div class="span7">
<input type="file" multiple class="file file-loading" data-preview-file-type="any" id="fileUp" name="fileUp[]">
</div>
</div>
</form>
and in the controller i have this for upload file
const Helpers = use('Helpers')
const myFile = request.file('fileUp')
const directory = Helpers.publicPath()
await myFile.move(directory, {
overwrite: true
})
but return error "move is not function"
i don't understand
Your input is for multiple files (fileUp[]), the docs has a section for multiple file upload,you should use moveAll() instead of move()
await profilePics.moveAll(Helpers.tmpPath('uploads'))
if (!profilePics.movedAll()) {
return profilePics.errors()
}

How to display image from selected id

I'm trying to display the info of the user when I get the id using $routeParams.id, I already displayed the user's info using texts only but how can I display the user's image using img src?
In my controller I did this to get the selected user.
.controller('editbloodrequestCtrl', function($scope,$routeParams, Bloodrequest) {
var app = this;
Bloodrequest.getBloodrequest($routeParams.id).then(function(data) {
if (data.data.success) {
$scope.newLastname = data.data.bloodrequest.lastname;
$scope.newFirstname = data.data.bloodrequest.firstname;
$scope.newImg = data.data.bloodrequest.img;
app.currentUser = data.data.bloodrequest._id;
} else {
app.errorMsg = data.data.message;
}
});
});
Now that I get the users info, I displayed this in my frontend
<label>Lastname:</label>
<input class="form-control" type="text" name="lastname" ng-model="newLastname">
<label>Firstname:</label>
<input class="form-control" type="text" name="firstname" ng-model="newFirstname">
<label>Image:</label>
<img src ="" name="img" ng-model="newImg"> //how can I display the image here?
Sample Documents:
{firstname:"James",lastname:"Reid",img:"random.jpg"}
My output:
No need to bind ng-model to your image, just use the src with the absolute path of the image
<img src ="{{newImg}}" name="img">
No need to bind ng-model to your image, just use the src with the absolute path of the image..ng-model using only input tags.
<img ng-src ="newImg" name="newimg" />

how to read xml file content from file in react?

I'm sure this question has been asked before but i can't find it in Stakoverflow
i'm doing a simple site where you upload an xml and it parses it to json.
i'm having a form to upload the xml:
<form onSubmit={this.handleSubmit}>
<label>
Upload file:
<input
type="file"
ref={input => {
this.App = input;
}}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
and my lisenter:
handleSubmit(event) {
//here the file will be opened
//submit pressed
event.preventDefault();
alert(
`Selected file - ${this.App.files[0].name}`
);
}
how do i extract the xml content from the file in the event ?
i want to have a String with the xml content from the file
thnx !!!
Found it i used this code:
var rawFile = new XMLHttpRequest();
var allText;
rawFile.open("GET", this.App.files[0], false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
allText = rawFile.responseText;
// alert(allText);
}
}
}
rawFile.send(null);

How can I hide whmcs buttons?

Hi I hope someone can help on the client details page I need to hide the Email forwarding button and the DNS management button if the client has selected custom nameservers. I just can't work it out son any help is much welcomed ..Here is the code that takes the input;
<form method="post" action="{$smarty.server.PHP_SELF}?action=domaindetails">
<input type="hidden" name="sub" value="savens">
<input type="hidden" name="id" value="{$domainid}">
<p><input type="radio" name="nschoice" value="default" id="nschoicedefault" onclick="usedefaultns()"{if $defaultns} checked{/if} /> <label for="nschoicedefault">{$LANG.nschoicedefault}</label><br />
<input type="radio" name="nschoice" value="custom" id="nschoicecustom" onclick="usecustomns()"{if !$defaultns} checked{/if} /> <label for="nschoicecustom">{$LANG.nschoicecustom}</label></p>
And here is the code for the buttons;
{if $emailforwarding}
<td><form method="post" action="{$smarty.server.PHP_SELF}?action=domainemailforwarding">
<input type="hidden" name="domainid" value="{$domainid}">
<p align="center">
<input type="submit" value="{$LANG.domainemailforwarding}" class="button">}
</p>
</form></td>
{/if}
{if $dnsmanagement}
<td><form method="post" action="{$smarty.server.PHP_SELF}?action=domaindns">
<input type="hidden" name="domainid" value="{$domainid}">
<p align="center">
{<input type="submit" value="{$LANG.domaindnsmanagement}" class="button">}
</p>
</form></td>
{/if}
I suggest writing a helper function and calling it at the top of the tpl file
and passing the domain id to it.
You can then use the WHMCS internal API function Domain Nameservers to get the domains nameservers then compare them against the default nameservers in the tblconfiguration in the WHMCS database.
Something like this
{php}
// include our helper php file
require_once(dirname(__FILE__).'/Helper.php');
//get domain id from our template variables
$domainid = $this->get_template_vars('domainid');
//call to our helper function passing the domain ID
$hasCustomeNameServers = Helper::hasCustomNameServers($domainid);
//Once we've compared the nameservers agains the default ones we write
//our binary check to the template
if($hasCustomeNameServers >0){
$this->assign('hasCustomeNameServers',true);}
{/php}
Then in side our Helper.php we have something like the following
<?php
class Helper {
public static function hasCustomNameServers($domainid) {
$isCustom = 0;
//Interal API call to get the domains nameservers
$command = "domaingetnameservers";
$adminuser = "admin";
$values["domainid"] = $domainid;
$results = localAPI($command,$values,$adminuser);
//get default nameservers
$defautName1 ='';
$sql = mysql_query('SELECT value FROM tblconfiguration '.
' WHERE setting = "DefaultNameserver1"');
if ($res = mysql_fetch_assoc($sql)) {
$defautName1 = $res["value"];}
$defautName2 ='';
$sql = mysql_query('SELECT value FROM tblconfiguration '.
' WHERE setting = "DefaultNameserver2"');
if ($res = mysql_fetch_assoc($sql)) {
$defautName2 = $res["value"];}
//compare results
foreach ($results as &$value) {
if($value == $defautName1 || $value == $defautName2){
$isCustom++;
}
}
return $isCustom;
}
}
Now it's simply a matter on the template to wrap the {if $emailforwarding} and the {if $dnsmanagement} blocks around our check {if !hasCustomeNameServers}
I hope this helps you in the right direction this is by no means a comprehensive answer but is a guide towards the approach I think you should take in implementing your solution.

Resources