I am able to upload images using Node.Js and Multer. The images are saving in encrypted format with random names. How can I retrieve and display images in a .jade file or .hetml file?
//My Code to upload image
router.post("/upload", function(req, res, next){
if (req.files) {
console.log(util.inspect(req.files));
if (req.files.myFile.size === 0) {
return next(new Error("Hey, first would you select a file?"));
}
fs.exists(req.files.myFile.path, function(exists) {
if(exists) {
res.end("Got your file!");
} else {
res.end("Well, there is no magic for those who don’t believe in it!");
}
});
}
});
// Upload page (Jade file)
form#fileUpload(method="post" action="/uploads/upload" enctype="multipart/form-data")
label(for="payload") Select a file to upload:
input#fileToUpload(type='file', name='myFile')
//input#payload(type="file" name="myFile" accept="image/*")
br
button#upload Upload
var multer = require('multer'),
upload = multer({dest: 'uploads/'});
app.post('/multipart-upload', upload.single('file'), function(req, res){
var filename = req.file.path;
console.log('Uploading File: ' + JSON.stringify(req.file));
});
Multer needs a path to upload the file. You can keep the path inside the public/static folder of express, and directly link the file.
Or You can use the static files middleware to serve the files in the upload folder and directly link them.
app.use('/image-uploads', express.static('uploads'));
Related
I want to realize uploading files for my users. I use CKEDITOR 5 in my react project. Back-end on nodeJS.
So, i can upload file, can get its Url, but, can't display one in VIEW page.
//my server code
const express = require('express');
//for uploading i use this module
const multiparty = require('connect-multiparty');
const multipartyMiddleware = multiparty({uploadDir: '/var/www/group0384.ru/public_html/server/uploads'}) //here is whole path to my upload folder on server
const app = express();
const port = 3555;
const path = require('path');
const moment = require('moment');
const fs = require('fs');
//so, here i have route /upload, which is indicated in configuration of ckeditor as route to send pictures
app.use(express.static("uploaded"));
app.post('/upload', multipartyMiddleware, (req, res) => {
var TempFile = req.files.upload;
var TempPathfile = TempFile.path;
const targetPathUrl = path.join(__dirname,"./uploaded/"+TempFile.name);
if(path.extname(TempFile.originalFilename).toLowerCase() === ".png" || ".jpg"){
fs.rename(TempPathfile, targetPathUrl, err =>{
res.status(200).json({
uploaded: true,
url: `${__dirname}/uploaded/${TempFile.originalFilename}`
}); // this path is the same as in 5th row (except folder, here it change, but it's no matter)
if(err) return console.log(err);
})
}
})
//------------CKEDITOR CODE---//
<CKEditor
editor={ClassicEditor}
data={this.state.data}
onChange={(event, editor) => {
this.setState({
data: editor.getData(),
});
}}
config={
{
ckfinder: {
uploadUrl: '/upload'
} // here, /upload - the route to send pictures
}
}
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
On my VIEW page, i getting this
screenshot
So, i've tried to change paths, but still couldn't get the picture.
please explain why I can't just get and output a file that is already uploaded on my own server
P.S. Sorry for my english
It seems from the screenshot that you are getting the absolute path to the image, if you want to show the image on the client-side and you are sure the image is saved on your server, you have to send it back as a public URL address of your image!
example: "http://example.com/images/image1.png"
Thank you all for answers, i resolved the problem.
In this part i change url for uploaded images
res.status(200).json({
uploaded: true,
url: `/files/${TempFile.originalFilename}`
});
Then, i created route with this url
app.get('/files/:url(*)', (req, res) => {
console.log(req.params.url)
res.sendFile(path.resolve(__dirname + '/uploaded/' + req.params.url))
})
And it works!
I'm trying to store an uploaded file,the file reached the server successfully but don't know how to store it using the multiparty library that's the code:
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
app.post('/upload_audio', multipartMiddleware, function(req, resp) {
console.log(req.body, req.files);
if(req.files){
resp.status(200).send("Uploaded!!!");
}
});
By default the 'connect-multipart' module save the file in a default file which is
"C://Users//ur-username//AppData//Local//Temp" but you can change it by adding this line :
app.use(multipart({ uploadDir: "ur_path"}));
I intended to use multer to upload multiple file and then rename them back to their original names. The below are the sample code:
var express = require('express');
var app = express();
var fs = require("fs");
var multer = require('multer');
app.use(express.static('public'));
var upload = multer({ dest: './upload/' });
app.get('/index.html', function (req, res) {
res.sendFile(__dirname + "/" + "index.html");
})
app.post('/file_upload', upload.array('theFile', 2), function (req, res, next) {
var errorcode = 0;
for (var i = 0; i < req.files.length; i++) {
fs.rename(req.files[i].path, req.files[i].destination + req.files[i].originalname, function (err) {
errorcode = err;
}(i));
}
if (errorcode != 0) {
console.log("errorcode is " + errorcode);
res.sendStatus(500);
return;
} else {
res.json({
message: 'File uploaded successfully',
});
}
})
var server = app.listen(8089, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
I'm testing the above code on a windows server. And my observation is that the files can be uploaded successfully but the fs.rename() keeps returning error "1". And the renamed files in the targeted folder are always 1Kb. It seems that the rename function intends to fetch the files which might be still uploading. I'm not sure whether my understanding is correct. If so, is there a way to determine whether the files have been uploaded completely? Any suggestion for my problem?
Why not use Multer's built-in renaming functionality?
Adapted from the documentation:
var storage = multer.diskStorage({
destination: '/path/to/uploads/folder',
filename: function (req, file, cb) {
// Here we specify the file name to save it as
cb(null, file.originalname);
}
})
// And we can use it for example like this:
app.post('/upload', upload.single('image'), function (req, res, next) {
// req.file is the `image` file
// req.body will hold the text fields, if there were any
})
However, there are a couple things you should be aware of if you take this approach:
The client can send any type of file, with any (potentially incorrect) extension. This is a potential security risk.
If two files are uploaded with the same name, the second file will overwrite the first.
If you serve these files to other users, the security risk greatly increases. An attacker could create a script or HTML page and upload it, possibly giving it a different file name extension. There are several ways it could be run, such as if the user tries to open it in a new tab because an image didn't show up. The full implications of this, and how to deal with it, are a topic of their own.
Finally, make very, very, sure that the user cannot write to a directory other than the uploads folder. What happens when file.originalname is something like ../../index.js? It may be better to convert the file name to a slug.
does anyone know how to use tinyPNG's API with multer? The docs seem deceptively simple:
var source = tinify.fromFile("unoptimized.jpg");
source.toFile("optimized.jpg");
though there's no clear indication of where this is meant to go, especially in something as convoluted as this:
var storage = multer.diskStorage(
{
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
//use date to guarantee name uniqueness
callback(null, file.originalname + '-' + Date.now());
}
}
);
//.any() allows multiple file uploads
var upload = multer({ storage : storage}).any()
app.post('/api/photo', function(req,res){
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
res.end("File is uploaded");
});
});
Where am I meant to "intercept" the file uploaded by multer so that I can compress it with tinyPNG?
Thanks in advance for the help!
Use following basic sample that changes uploaded photo/gallery files:
// Import express and multer.
var express = require('express');
var multer = require('multer');
// Setup upload.
var upload = multer({ dest: 'uploads/' });
var multipleFiles = upload.fields([{ name: 'photo', maxCount: 1 },
{ name: 'gallery', maxCount: 8 }]);
// Setup tinify.
var tinify = require("tinify");
tinify.key = "YOUR_API_KEY";
// Get request handler for '/' path.
var app = express();
app.get('/', function (req, res) {
res.setHeader("Content-Type", "text/html");
res.end(
"<form action='/api/photo' method='post' enctype='multipart/form-data'>" +
"<input type='file' name='photo' />" +
"<input type='file' name='gallery' multiple/>" +
"<input type='submit' />" +
"</form>"
);
});
// Upload file handler with '/api/photo' path.
app.post('/api/photo', multipleFiles, function (req, res) {
req.files['gallery'].forEach(function(file) {
// Your logic with tinify here.
var source = tinify.fromFile(file.path);
source.toFile(file.path + "_optimized.jpg");
});
res.end("UPLOAD COMPLETED!");
});
Feel free to change express middleware how you need it, just make sure you use upload.fields and authenticate using tinify.key = "YOUR_API_KEY";
https://github.com/expressjs/multer
https://tinypng.com/developers/reference/nodejs#compressing-images
I recently worked out a similar problem for myself using the tinify package and found the docs to be somewhat lacking.
I have a Vue front end collecting file uploads from the user using vue2dropzone. These are sent to a node / Express back end.
I have a need to compress the file and upload it to an S3 instance without storing on disk. That means using multer memory storage.
As a result there won’t be an ability to use tinify.fromFile() as there is no file stored locally.
In my images middleware:
Const multer = require(“multer”);
const tinify = require("tinify");
tinify.key = "your_key";
exports.singleFile = multer({ storage: multer.memoryStorage() }).fields([{ name: "file", maxCount: 1 }]);
exports.uploadCompImage = async (req, res, next) => {
try {
const fileName = `${req.params.name}${path.extname(req.files.file[0].originalname)}`;
const source = tinify.fromBuffer(req.files.file[0].buffer);
source.store({
service: "s3",
aws_access_key_id: "your_id",
aws_secret_access_key: "your_key
region: "your_region",
headers: {
"Cache-Control": "public"
},
path: `your_bucket/your_folder/${fileName}`
});
return res.status(200).send(`path_to_file/${fileName}`)
} catch (err) {
console.log(err);
next(err);
}
}
Then in my routes file:
Const images = require(“../middleware/images”);
// skipped several lines for brevity
productRouter
.route("/images/:name")
.post(images.singleFile, images.uploadCompImage)
This process creates a multer singleFile upload to memoryStorage, making the file available at req.files.file[0] (req.files[“file”] because I specified “file” as the name in multer fields, loop through this array if uploading multiple).
After setting that up I get the file name, set the source by using tinify to read from req.files.file[0].buffer as a buffer.
Then I set the source to my s3 instance and send back a public link to the file.
Hopefully this answer helps you. I could definitely see altering the process to change where the file goes or even write it to disk by altering the multer options.
I am new to node.js .And need to upload an image when an api is called,the image is given as multipart form data.
How could i get the image details as the response?
You can use multer.js as the body-parser. Its built on top of busboy.
Its quite well-documented .
The answer of this question is as follow :
fileupload.js :
var express = require("express"),
app = express();
// tell express to use the bodyParser middleware
// and set upload directory
app.use(express.bodyParser({ keepExtensions: true, uploadDir: "uploads" }));
app.engine('jade', require('jade').__express);
app.post("/upload", function (request, response) {
// request.files will contain the uploaded file(s),
// keyed by the input name (in this case, "file")
// show the uploaded file name
console.log("file name", request.files.file.name);
console.log("file path", request.files.file.path);
response.end("upload complete");
});
// render file upload form
app.get("/", function (request, response) {
response.render("upload_form.jade");
});
app.listen(3000);
View :
doctype 5
html
head
title Upload Form
body
h1 Upload File
form(method="POST", action="/upload", enctype="multipart/form-data")
input(type="file", name="file")
input(type="submit")