Upload zip files to service for user download - node.js

I have an express (node.js) application that creates mp3 files for a user and stores them in a folder on the server.
The server's file structure looks like this:
data/
id#/
song1.mp3
song2.mp3
song3.mp3
id#/
song1.mp3
song2.mp3
song3.mp3
...
I want to create zip files and download links for the folder and email users their zip file. Each folder is named using an id# and corresponds to a user.
I want to use an external service (such as s3) to store and handle the downloads of the files.
How would I zip up the files and send them to the service and create download links? Which services should I look into?

you can use the child_process module to run a zip command in the background (this example is for say if you're on Linux, you can modify it to suit windows)
This just handles the zip process, then you can respond with the link to download the file:
var exec = require('child_process').exec;
var currentWorkingDirectory = '/data', // Folder that contains the sub folders of id#/
folderToZip = 'id123123', // Subfolder name id#, e.g. id123123
tmpFolderForZips = '/tmp/', // Folder to store the zip files in
execString = "zip -r " + tmpFolderForZips + folderToZip + ".zip " + folderToZip; // Tidy string to put it all together
console.log(execString);
var child = exec(execString, { cwd: currentWorkingDirectory });
child.on('error', function(err) {
console.log(err);
})
child.on('close', function() {
// respond with download link to zip file
console.log('Done Zipping');
});
Make sure you apt-get install zip

Related

How to download files in azure blob storage into local folder using node js

I am using node js to download azure blob storage files into our local machine. I am able to download it into my project path but not able to download into my local machine. I am using html, Express,and node js. Currently working on localhost only. How to download ?
Below is the code that i am using to download blob file to local folder.
app.get("/downloadImage", function (req, res) {
var fileName = req.query.fileName;
var downloadedImageName = util.format('CopyOf%s', fileName);
blobService.getBlobToLocalFile(containerName, fileName, downloadedImageName, function (error, serverBlob) {
});
});
I am able to to download it to my project folder but i want to download it to my downloads folder. Please help me on this ?
To download a file from Azure blob storage
ConnectionString: Connection string to blob storage
blobContainer: Blob Container Name
sourceFile: Name of file in container i.e sample-file.zip
destinationFilePath: Path to save file i.e ${appRoot}/download/${sourceFile}
const azure = require('azure-storage');
async function downloadFromBlob(
connectionString,
blobContainer,
sourceFile,
destinationFilePath,
) {
logger.info('Downloading file from blob');
const blobService = azure.createBlobService(connectionString);
const blobName = blobContainer;
return new Promise((resolve, reject) => {
blobService.getBlobToLocalFile(blobName, sourceFile, destinationFilePath, (error, serverBlob) => {
if (!error) {
logger.info(`File downloaded successfully. ${destinationFilePath}`);
resolve(serverBlob);
}
logger.info(`An error occured while downloading a file. ${error}`);
reject(serverBlob);
});
});
};
According to the reference of the method blobService.getBlobToLocalFile, as below, the value of parameter localFileName should be the local file path with related dir path.
localFileName string The local path to the file to be downloaded.
So I created a directory named downloadImages and changed your code as below.
var downloadDirPath = 'downloadImages'; // Or the absolute dir path like `D:/downloadImages`
app.get("/downloadImage", function (req, res) {
var fileName = req.query.fileName;
var downloadedImageName = util.format('%s/CopyOf%s', path, fileName);
blobService.getBlobToLocalFile(containerName, fileName, downloadedImageName, function (error, serverBlob) {
});
});
It works for me, the image file was downloaded into my downloadImages directory, not under the path of my node app.js running.
Note: If you want to deploy it on Azure WebApp later, please must use the absolute directory path like D:/home/site/wwwroot/<your defined directory for downloading images>, because the related directory path is always related the path of IIS started up node.

express fileupload : no such file or directory

I am using express-file package. I use it like this:
const upload = require('express-fileupload');
app.use(upload({
createParentPath: true
}));
This is how I store:
await req.files.main_image.mv('./public/images/movies/'+main_image);
I already have public/images directory created. I don't have movies directory in public/images directory though.
When It works: If I have /public/images/movies directory already created, it works
When it doesn't work: If I don't have /public/images/movies directory created, but have /public/images directory. Then it says:
ENOENT: no such file or directory, open
'C:\Users\glagh\Desktop\Work\MoviesAdviser\public\images\movies\1554741546720-8485.11521.brussels.the-hotel-brussels.amenity.restaurant-AD3WAP2L-13000-853x480.jpeg
What to do so that it automatically creates /movies directory and put the image there?
Express-fileupload uses the following code to create the directory-path which you pass to the .mv function:
const checkAndMakeDir = function(fileUploadOptions, filePath){
//Check upload options were set.
if (!fileUploadOptions) return false;
if (!fileUploadOptions.createParentPath) return false;
//Check whether folder for the file exists.
if (!filePath) return false;
const parentPath = path.dirname(filePath);
//Create folder if it is not exists.
if (!fs.existsSync(parentPath)) fs.mkdirSync(parentPath);
return true;
};
The problem is that fs.mkdirSync() does not create the full path with the parent directories you specifiy (note that you'd use mkdir -p on the shell to create the whole folder structure) -> checkout How to create full path with node's fs.mkdirSync? for more information.
What you could do is use a module like fs-extra and use its function ensureDir which would create the corresponding parent directories (if they don't exist yet) before calling the .mv() function.
Or in case you're node version is >= 10 use the native {rescursive:true} option which you can pass to fs.mkdirSync.

how to upload image to backblaze using hapijs

I am trying to upload image to backblaze-b2 using hapi.js. I am using a plugin called easy-backblaze but while using it I need to mention the path of the file. But While importing the file using Hapijs I am not able to understand how to get that path.
This is the Code I have written and here in b2.uploadFile I need to mention the path of the file on local Drive:
var B2 = require('easy-backblaze');
var b2 = new B2('accountId', 'applicationKey');
b2.uploadFile('C:/Users/Lovika/Desktop/addDriver.png', {
name: 'addDriver.png', // Optional, renames file
bucket: 'testBucket', // Optional, defaults to first bucket
}, function(err, res) {
console.log('Done!', err, res);
});
Do I need to upload the file to the server first and then to backblaze or Is there any way to upload the file directly to backblaze

Extract a specific folder from a zip file using node.js

I have a zip file with the following structure:
download.zip\Temp\abc.txt
download.zip\Temp\Foo\abc2.txt
I want to extract the content under Temp in download.zip to a directory say D:\work_del.
This directory after extraction of zip should have abc.txt and Foo\abc2.txt
I am using adm-zip module of node but that doesn't seem to help. (Below code for reference).
var zip = require('adm-zip');
var file = new zip("D:\\Work\\download.zip");
file.extractEntryTo("Temp", 'D:\\Work_delete', false, true);
Any pointers to get the above the scenario working in node.js?
var zip = require('adm-zip');
var file = new zip("D:\\Work\\download.zip");
file.extractEntryTo("Temp/abc.txt", 'D:\\Work_delete', false, true);
The thing that I noticed is that if you specify the path as Temp\\1.txt it doesn't work. So try to avoid backslashes as forward slashes work perfectly fine in Windows with Node.js.
var zip = require('adm-zip');
var file = new zip("C:/Users/harslo/Desktop/node/Download.zip");
file.extractEntryTo("Temp/abc.txt", 'C:/Users/harslo/Desktop/node/Work_delete', false, true);
If you want to extract all the files inside of a folder use FolderName/ as described in adm-zip docs docs.
PS - ADM-ZIP extractEntryTo doesn't seem to be working with zips created with Windows Inbuilt "Send to ZIP".
var zip = require('adm-zip');
var file = new zip("D:/Work/download.zip");
file.extractEntryTo("Temp/", "D:/Work_delete", false, true);

How to link files in NodeJS (+ let the user download the file when clicking it)?

I guess it is just a simple question but I can't solve it on my own.
(I'm using Express + NodeJS)
What I would like to have is a directory listing with the files contained in it. The files shall be linked so that a user could download them by just clicking the link (like the standard directory listing you get if you have e.g. a apache server without any index file).
To list the directory content I use
var fs = require('fs');
fs.readdir('./anydir', function(err, files){
files.forEach(function(file){
res.send(file);
});
});
(Notice: I did not include any error handling in this example as you can see)
Now I tried to just link the file by modifying the
res.send(file)
to
res.send('<a href=\"' + file + '\">' + file + '<br>');
but this just prints out the error message:
Cannot GET /anydir/File
... because I did not handle every file request in app.js.
How can I achieve my goal mentioned above?
Just use express.directory and express.static as middleware, possibly with a user-defined middleware to set Content-Disposition headers.
This worked for me:
var fs = require('fs');
fs.readdir('/var/', function(err, files){
files.forEach(function(file){
res.write('<a href=\"' + file + '\">' + file + '<br>');
});
});
You put the content with write() not send().
Try this and let me know. I can see the list of files displayed correctly.
Hope this helps you.

Resources