trying to figure out how to crop to square using graphicmagick for node.js with imagemagick , but how do I pass the ^ flag to the thumbnail method so that it crops
var gm = require('gm')
.subClass({imageMagick: true}); // Enable ImageMagick integration.
gm(inPath).thumb('200','200^').scale('5%').scale('2000%').write(outPath, function(err, results){
if (err) console.error(err);
console.log(results);
});
so it looks like I had to use the thumbnail method instead of thumb if I wanted to pass in the ^ in the resize
e.g.
gm(inPath).thumbnail('200','200^')
Related
I want to upload Powerpoint files to Google drive. When I do this using the UI (clicking on "Upload File" and uploading a file), things work as I expect. However, when I use the Drive API I get some formatting issues. For example, the shading (text highlight) in my Powerpoint tables is transparent, but when I upload to Drive using the API the shading becomes white.
I have tried to work around this by specifying MIME type as application/vnd.google-apps.file, but when I get the response, the MIME type shows as application/vnd.google-apps.presentation
I am using Google Drive API v3, accessed through the R package googledrive.
Try to use this mimeType : application/vnd.openxmlformats-officedocument.presentationml.presentation
including :
application/vnd.google-apps.file
Here is an example done with NodeJS, try and let me know if it works well for you.
Just in case, try other mimeTypes (url is provided on Reference list, scroll down)
var fileMetadata = {
'name': '___Your File Name Here___',
'mimeType': 'application/vnd.google-apps.file'
};
var media = {
mimeType: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
body: fs.createReadStream('___Your File Name Here___.pptx')
};
function uploadFile(auth){
const drive = google.drive({version: 'v3', auth});
drive.files.create({
resource: fileMetadata,
media: media,
fields: 'id'
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
})
}
// RUN script
fs.readFile('credentials.json', (err, content) => {
if (err) {
console.log('Error loading client secret file: ' + err);
return;
}
authorize(JSON.parse(content), uploadFile);
});
References:
Google mimeTypes (Google Reference)
List of mimeTypes (MDN)
Ok, so I am using the typical image minification process. I have functions for jpg, pngs and I have a separate function to convert those to webp.
I have the following gulpfile (only the relevant parts are here):
function clean(done) {
rimraf(folder.public_img, done);
}
function images() {
return gulp.src([folder.preimages+'/**/*.{gif,png,jpg,svg}'])
.pipe(cache(imagemin([
imageminPngquant({
speed: 1,
quality: [0.95, 1]
}),
imageminZopfli({
more: true
}),
imageminMozjpeg({
quality: 65
}),
])))
.pipe(gulp.dest(folder.public_img));
}
gulp.task('webp', () =>
gulp.src([folder.preimages+'/**/*.{gif,png,jpg}'])
.pipe(webp({
quality: 65,
method: 6
}))
.pipe(gulp.dest(folder.public_img))
);
function serve() {
gulp.watch(folder.preimages+"/**/*.{gif,png,jpg,svg}", images);
gulp.watch(folder.preimages+"/**/*.{gif,png,jpg}", webp);
}
gulp.task('clean', clean);
gulp.task('images', images);
gulp.task('serve', gulp.series('clean', 'images', 'webp', serve));
gulp.task('default', gulp.series('clean', 'images', 'webp', serve));
So, basically when I run gulp the first time, all the processes run fine and the webp images are generated. BUT, if I add a new image, the images() function runs, but for some reason the webp() function doesn't execute, it's as if it doesn't see changes, and I have it configured the same way as images.
I tried two alternatives:
I added the webp process directly inside the images() function, but that way my JPG and PNG files were directly converted to webp and I didn't have fallback images.
I tried to create the webp function with the same format as the others function webp() { ... }, but when I tried to run gulp it showed this error:
The following tasks did not complete: default,
Did you forget to signal async completion?
So I found that I could use the format above gulp.task('webp', () =>... and that works, but doesn't respect the watch function. I think it could be related to the function to name assignation in the end of the file, but I am not that familiar with the syntax.
What should I change so that it watches correctly?
I was able to recreate your code and get it to work as follows:
In creating your gulp tasks, something goofy seems to be happening because you've created a series of tasks to run with your gulp.task('serve'). Instead, you can write out your tasks like this:
gulp.task(clean);
gulp.task(images);
gulp.task(serve);
gulp.task('default', gulp.series(clean, images, webp, serve));
You may want to call your webp function something else - I was getting a conflict because of also importing gulp-webp as const = webp. You also don't need to put quotation marks around the name of the function in the task and then also reference it in the task again. So gulp.task(clean) works just fine. You don't need gulp.task('clean', clean).
You can probably also write your default task as follows:
gulp.task('default', gulp.series(clean, serve);
This had the same effect for me as also including the images and webp tasks in the series. This setup worked for me. Running gulp, it first ran the clean function to remove the public_img folder, then ran images followed by webp. It worked up the initial run as well as when I added a new image to the preimages folder.
Update
Here's the complete gulpfile I got to work:
const gulp = require('gulp');
const imagemin = require('gulp-imagemin');
const rimraf = require('rimraf');
const webp = require('gulp-webp');
const folder = {
preimages: 'src/images',
public_img: 'src/public_img',
};
function clean(done) {
rimraf(folder.public_img, done);
}
function images() {
return gulp
.src([folder.preimages + '/**/*.{gif,png,jpg,svg}'])
.pipe(imagemin())
.pipe(gulp.dest(folder.public_img));
}
function webpTask() {
return gulp
.src([folder.preimages + '/**/*.{gif,png,jpg}'])
.pipe(webp())
.pipe(gulp.dest(folder.public_img));
}
function serve() {
gulp.watch(folder.preimages + '/**/*.{gif,png,jpg,svg}', images);
gulp.watch(folder.preimages + '/**/*.{gif,png,jpg}', webpTask);
}
gulp.task('clean', clean);
gulp.task('images', images);
gulp.task('default', gulp.series('clean', 'images', webpTask, serve));
Notes: I removed the gulp serve task. I couldn't get that to work under any configuration. I think you are running into a conflict by naming both the task and the function serve, although I'm not 100% positive. I changed the webp task name to webpTask, as I was getting a conflict by naming both the webp import and the webp function webp. I didn't include any of the webp() or imagemin() configuration options, but that shouldn't matter.
You should also be able to remove the calls for both the images and webpTask functions in the gulp default task, as running the serve function should trigger both of those.
This setup worked for me both when adding new images to my preimages folder while the gulp default task was running as well as when restarting the gulp default task.
FYI: I'm using gulp version 4.0.1., but I don't think that should make a difference for this.
I'm trying to use lambda to restore a table in dynamoDB,
but keep getting this error message.
TypeError: dynamodb.restoreTableFromBackup is not a function
Could anyone tell me how to fix it?Thanks~
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#restoreTableFromBackup-property
'use strict';
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = (event, context, callback) => {
const params = {
BackupArn: 'arn:aws:dynamodb:us-east-1/xxxxx',
TargetTableName: 'xxx',
};
dynamodb.restoreTableFromBackup(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
};
I ran the code you provided in my own lambda and got the same result.
It seems the AWS SDK that is provided natively in Lambda isn't the latest version, with the restoreTableFromBackup function.
If I do the same test while using the latest available in npm, it seems to work fine.
As a work around, I suggest uploading your lambda as a zip file, and including the the node_modules/aws-sdk along with your code.
This will ensure it uses the latest aws-sdk which includes the restoreTableFromBackup function.
To assist further, I've written a walk through of how to use On-Demand backups / restore and how to schedule these backups.
https://www.abhayachauhan.com/2017/12/dynamodb-scheduling-on-demand-backups
HTH
'npm install aws-sdk' in Cloud9 terminal for the Lambda
I have a simple nodejs project that should load asynchronously the google maps api javascript, i followed this answer https://stackoverflow.com/a/15796543
and my app.js is like this:
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
methodOverride = require("method-override");
https = require("https");
requirejs = require('requirejs');
requirejs.config({
waitSeconds : 500,
isBuild: true,
paths : {
'async': 'node_modules/requirejs-plugins/src/async',
}
});
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(methodOverride());
var router = express.Router();
router.get('/', function(req, res) {
res.send("Hello World!");
});
requirejs(["async!http://maps.google.com/maps/api/js?key=mykey&sensor=false"], function() {
console.log(google);
});
app.listen(3000, function() {
console.log("asd");
});
package.json:
{
"name": "rest-google-maps-api",
"version": "2.0.0",
"dependencies": {
"express": "^4.7.1",
"method-override": "^2.1.2",
"body-parser": "^1.5.1",
"requirejs": "2.3.3",
"requirejs-plugins": "1.0.2"
}
}
i've got always the same error:
ReferenceError: google is not defined
The main issue here is that you are trying to run in Node code that is really meant to be used in a browser.
The async plugin
This plugin needs to be able to add script elements to document and needs window. I see you set isBuild: true in your RequireJS configuration. It does silence the error that async immediately raises if you do not use this flag, but this is not a solution because:
isBuild is really meant to be set internally by RequireJS's optimizer (or any optimizer that is compatible with RequireJS), not manually like you are doing.
isBuild means to indicate to plugins that they are running as part of an optimization run. However, your code is using the plugin at run time rather than as part of an optimization. So setting isBuild: true is a lie and will result in undesirable behavior. The async plugin is written in such a way that it effectively does nothing if isBuild is true. Other plugins may crash.
Google's Map API
It also expects a browser environment. The very first line I see when I download its code is this:
window.google = window.google || {};
Later in the code there are references to window.document and window.postMessage.
I don't know if it is possible to run the code you've been trying to load from Google in Node. I suspect you'd most likely need something like jsdom to provide a browser-like environment to the API.
assuming you did everything else correctly, which I am not testing here. The reason you are getting the error is because you call console.log(google) and there is no google variable. You need to pass google in as a reference in your call back function. This will either get rid of the error, or change the error if you have set up requirejs incorrectly.
requirejs(["async!http://maps.google.com/maps/api/js?key=mykey&sensor=false"],
function( **google** ) {
console.log(google);
});
see the requirejs docs http://requirejs.org/docs/node.html#1
I have a logo somewhere on my application page.
The application admin should be able to adjust the logo within the webapplication by simply upload a new one. What would be the best practice to achieve this?
How would I handle the upload on the server. It should replace the old logo with the new one. The name and location should stay the same.
Here is my approach:
I use the package UploadFS:
jalik:ufs
jalik:ufs-local
autopublish //it is still on, so the code below works without publish/subscribe I know that I will have to change that.
My code:
Upload
*.js Server & Client
//Almost Standard initialization - works so far
Logo = new Mongo.Collection('logo');
LogoStore = new UploadFS.store.Local({
collection: Logo,
name: 'logo',
path: '/uploads/logo',
mode: '0744', // directory permissions
writeMode: '0744', // file permissions
filter: new UploadFS.Filter({
minSize: 1,
maxSize: 1024 * 1000, // 1MB,
contentTypes: ['image/*'],
extensions: ['png']
})
});
*.html
//Standard initialization - works so far
<template name="upload">
<button type="button" name="upload">Select files</button>
</template>
*.js Client
//Almost Standard initialization - works so far
Template.upload.events({
'click button[name=upload]': function (ev) {
var self = this;
UploadFS.selectFiles(function (file) {
// Prepare the file to insert in database, note that we don't provide an URL,
// it will be set automatically by the uploader when file transfer is complete.
var logo = {
name: 'logo.png', //all uploaded images will have the same name
size: file.size,
type: file.type,
};
// Create a new Uploader for this file
var uploader = new UploadFS.Uploader({
// This is where the uploader will save the file
store: LogoStore,
// Optimize speed transfer by increasing/decreasing chunk size automatically
adaptive: true,
// Define the upload capacity (if upload speed is 1MB/s, then it will try to maintain upload at 80%, so 800KB/s)
// (used only if adaptive = true)
capacity: 0.8, // 80%
// The size of each chunk sent to the server
chunkSize: 8 * 1024, // 8k
// The max chunk size (used only if adaptive = true)
maxChunkSize: 128 * 1024, // 128k
// This tells how many tries to do if an error occurs during upload
maxTries: 5,
// The File/Blob object containing the data
data: file,
// The document to save in the collection
file: logo,
// The error callback
onError: function (err) {
console.error(err);
},
onAbort: function (file) {
console.log(file.name + ' upload has been aborted');
},
onComplete: function (file) {
console.log(file.name + ' has been uploaded');
},
onCreate: function (file) {
console.log(file.name + ' has been created with ID ' + file._id);
},
onProgress: function (file, progress) {
console.log(file.name + ' ' + (progress*100) + '% uploaded');
},
onStart: function (file) {
console.log(file.name + ' started');
},
onStop: function (file) {
console.log(file.name + ' stopped');
}
});
// Starts the upload
uploader.start();
// Stops the upload
uploader.stop();
// Abort the upload
uploader.abort();
});
}
});
Show uploaded Logo
*.html
<template name="whatever">
<img src="{{logoUrl}}" alt="Logo" >
</template>
*.js client only
Template.whatever.helpers({
logoUrl: function(){
return Logo.findOne().url;
}
})
So If I understand it right, what the code does is uploading the img to somewhere on the server. Also it stores some info about that image in a Mongo.Collection - Logo.
But I do not exactly know where those images are stored, in which folder. They are not stored in my default Project - Folder.
The url of an example img is: http://localhost:3000/ufs/logo/B4Fv5etkr7xQbvs5v/logo.png. That random string in the middle is the _id of that img. So I can not use a hardcoded url for that images to access them, because as soon as a new img is uploaded, that url will change completely.
Q1: So the first question is: Can I upload to the myProject/public/img folder directly? So that the url of the img would be something like:
http://localhost:3000/img/logo.png
Then I would need just to replace the old logo on the upload.
For now I have to deal with the generic url. So as next, I select the url of the now present image on the server from the Logo - collection and pass that url to my template to the place where the logo has to be placed. The problem with that is, that the url is loaded after everything else was loaded, so for several seconds I get an tag without an url in it. So that place shows the alt text only until the url is loaded. That is very ugly...
Q2: The question is, how could I get the url, before the tag is loaded. So that the logo appears with/before everything else, as if the url would be hardcoded in advance.
Q3: Is it possible to replace the old logo with the new uploaded one, on the upload? How?
Q4: If I delete the entry for the img from the Logo - Collection, is the image actually deleted from the server? Or do I have to delete it manually/in another way?
You can send a base64 encode image on server then using fs your can overwrite the file.
Like:
Client
readAsDataURL has base64 encoded data in the format of
data:image/jpeg;base64,/9j/4AAQSkZJRgABA...
So you need to get rid of the mime type and encoding information at the front.
contents = contents.split(',')[1];
Now you can send this base64 encoded data to server.
Server
Since you're receiving base64 encoded data, you can convert it buffer and write to file:
fs.writeFile(filepath, Buffer(argument,'base64'), err => {
//
})
In case the file name same as another file then it will completely overwrite your file.
Answer for question 1:
default image will be stored hide folder in your project .meteor/local/build/programs/server/ufs/uploads/
You can change destination by "path" as below code
new UploadFS.store.Local({
collection: Csvs.collection,
name: 'csv',
path: '../../../../../uploads/csv', //here change destination folder stored file
filter: new UploadFS.Filter({
maxSize: 1024 * 3000, // 3MB,
contentTypes: ['text/csv']
})
});
When doing the "Client" step in Pankaj Javav's answer, you may want to use the base64-image-upload package I whipped up, as I was having the same problem. It simplifies the process of uploading any base64 string to a server, and you do not need to get rid of the MIME type this way.