How do I save an image locally with HTML and JS? - javascript

I have an input that the user can upload an image, I want to get this image and pass it to the server side and the server will store this image on a local folder, for example:
I use linux for the server so the server.js is running from the folder /home/user/project/server/server.js. When the server get the image I want it to store on the folder /home/user/project/images/img.jpg
This my code:
HTML:
<input type="file" id="imageFile" accept=".jpg, .jpeg, .png" />
Front-End:
const signup = async () => {
const name = document.getElementById("signup_name").value;
const passwd = document.getElementById("signup_passwd").value;
const image = document.getElementById("imageFile").files[0];
let formData = new FormData();
formData.append("fileToUpload", image);
const response = await fetch("http:/localhost:3000/signup", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
nome: cadastro_nome,
senha: cadastro_senha,
imagem: formData
}),
});
const result = await response.json();
document.getElementById("cadastro_nome").value = "";
document.getElementById("cadastro_senha").value = "";
alert(result);
};
Back-End:
app.post("/signup", async (req, res) => {
const { name, passwd, image } = req.body;
if (!name || !passwd) {
return res.status(400).json("Dados incorretos!");
}
knex
.transaction((trx) => {
trx
.insert({
login: name,
senha: passwd,
divida: 0,
})
.into("usuarios")
.then(trx.commit)
.catch(trx.rollback)
.then(res.json("Cadastrado com sucesso!"));
})
.catch((err) => {
console.log(err);
return res.json("Login existente, tente novamente!");
});
//PUT SOMETHING HERE TO SAVE IMAGE LOCALLY, MAYBE??
});

Yes, you can first store the uploaded image as a Base64 string using the FileReader, data urls are already base64 so when you call reader.readAsDataURL the e.target.result sent to the reader.onload handler and it will be all you need, but also may need add in your HDD or do it asynchronous using res.json, check the WDN official documentation about FileReader.
(Get user's uploaded image for example)
const imgPath = document.querySelector('input[type=file]').files[0];
const reader = new FileReader();
reader.addEventListener("load", function () {
// Convert file to base64 string and save to localStorage
localStorage.setItem("image", reader.result);
}, false);
if (imgPath) {
reader.readAsDataURL(imgPath);
}
And to read the image back from the localStorage, just use querySelector or getElementById:
const img = document.getElementById('image');
img.src = localStorage.getItem('image');
About the "fd" argument must be of type number, in my case, sometimes I was using:
fs.readSync() when I should have been using fs.readFileSync()
fs.writeSync() usage but should be fs.writeFileSync()
fr.write() could be in your case fs.writeFile()
The comment of #Dimava in your question can work too, I flagged up.
For more help, consult this post related to your similar question! ;)

Related

How to convert async AsyncIterable<Uint8Array> to File in Javascript

Hello I'm sending/POST a File from a HTML Form on a browser client to a Remix application server.
The Remix applicaton server is sending/handling my File as a async AsyncIterable.
I now need to convert it back to a File object so I can send it to a backend server as FormData.
I tried both with and without buffer for demo:
Does anyone have experiance with convert AsyncIterable to Blob then to File??
const myHandler: UploadHandler = async ({ name, contentType, data, filename }) => {
//'data' is data of type AsyncIterable<Uint8Array>
//'contentType' is 'image/png'
let dataArray1 = []; //test1 without buffer
let dataArray2 = []; //test2 with buffer
for await (const x of data) {
dataArray1.push(x); //without buffer
dataArray2.push(x.buffer); //with buffer
}
const blob1 = new Blob(dataArray1, {type: contentType});
const blob2 = new Blob(dataArray2, {type: contentType});
const file1 = new File([blob1], filename, { type: contentType });
const file2 = new File([blob2], filename, { type: contentType });
console.log('file1.size: ', file1.size);
//file1 size is 1336843 (and for file2)
//but i'm getting content-length 1337028 from my browser Form
//so I'm not sure if it's correct
return file1;
};
[![content-length size][1]][1]
[![enter image description here][2]][2]
[![enter image description here][3]][3]
[![enter image description here][4]][4]
Try passing the blob parts directly into the file constructor.
const myHandler: UploadHandler = async ({ name, contentType, data, filename }) =>
{
const dataArray1 = [];
for await (const x of data)
{
dataArray1.push(x);
}
const file1 = new File(dataArray1, filename, { type: contentType });
return file1;
};

PouchDB can't convert blob into url for image src

Hey guys I'm working with PouchDB and react. File uploading is working normally but when I try to convert blob into url I'm having this error in console.
"Failed to execute 'createObjectURL' on 'URL': Overload resolution
failed."
I checked the return and I'm able to retrieve all the data/images into the console and basically see the file types and so on. Anyway I heard that "createObjectURL" is deprecated or so but I followed up the tutorial provided in docs for the PouchDB. So I'm not sure now. Can someone give me any insights or help on this ? Thanks
Snippet below:
// uploading files
const uploadF = e => {
// saving chosen file
const file = e.target.files[0];
// generating random number and converting it to the string
const random_id = Math.floor(Math.random() * 10000);
const random_id_to_string = String(random_id);
console.log(file);
// insert data into local DB
db.post({
_id: random_id_to_string,
_attachments: {
fileName: {
content_type: file.type,
data: file
}
}
})
// insert data into remote db
redb.post({
_id: random_id_to_string,
_attachments: {
fileName: {
content_type: file.type,
data: file
}
}
})
// upload file to s3 bucket
S3FileUpload.uploadFile(e.target.files[0],config)
.then(data => {
console.log(data);
})
.catch(err => console.log(err))
}
// retrieve all data from db
const files = [];
db.allDocs({
include_docs: true,
attachments: true
}).then(function (result) {
return result;
})
.then(function(blob){
const url = URL.createObjectURL(blob);
console.log(url);
})
.catch(function (err) {
console.log(err);
});
return(
<section className="hero">
<nav>
<h2>Welcome</h2>
<button onClick={handleLogout}>Logout</button>
<input type="file" onChange={e => uploadF(e)} />
</nav>
</section>
);

Cannot seem to retrieve image Files from FormData values in my Lumen PHP app

I have the following request to send image files to my PHP endpoint:
const formData = new FormData();
Object.keys(this.state.productData).forEach((key) => {
if (key === "files") {
formData.append(key, this.state.productData[key]);
}
});
for (let value of formData.values()) {
console.log(value);
}
fetch(`${process.env.REACT_APP_API_URL}/products/submit`, {
method: 'POST',
body: formData,
})
Now as proof the value i get from the console.log is this:
[object File]
In my PHP endpoint I do the following:
return response([$request->get('files')]);
This however results in:
["[object File]"]
Also
response([$request->hasFile('files'), $request->get('files')]);
returns: [true, null]
Any help to get my image files from my react app to php endpoint would be highly appreciated.
My Image files are stored into the stated as the "files" values after i upload them using: FileReader() in js:
handleImageChange = e =>{
e.preventDefault();
let files = Array.from(e.target.files);
files.forEach((file, i) => {
let reader = new FileReader();
reader.onloadend = () => {
this.setState(prevState => ({
files: [...prevState.files, file],
imagesPreviewUrls: [...prevState.imagesPreviewUrls, reader.result]
}));
};
reader.readAsDataURL(file);
});
};
To retrieve image files from FormData values in your Lumen PHP application, you need to do the following:
return response([$request->file('files')]);

How to get file properties and upload a file from ionic 4?

I am trying to upload a file from mobile to google bucket using ionic 4. Although a file can upload into the could. I am struggling to get the file properties out of file object.
Here is my method,
async selectAFile() {
const uploadFileDetails = {
name: '',
contentLength: '',
size: '',
type: '',
path: '',
};
this.fileChooser.open().then(uri => {
this.file.resolveLocalFilesystemUrl(uri).then(newUrl => {
let dirPath = newUrl.nativeURL;
const dirPathSegments = dirPath.split('/');
dirPathSegments.pop();
dirPath = dirPathSegments.join('/');
(<any>window).resolveLocalFileSystemURL(
newUrl.nativeURL,
function(fileEntry) {
uploadFileDetails.path = newUrl.nativeURL;
const file: any = getFileFromFileEntry(fileEntry);
//log 01
console.log({ file });
uploadFileDetails.size = file.size;
uploadFileDetails.name = `${newUrl.name
.split(':')
.pop()}.${file.type.split('/').pop()}`;
uploadFileDetails.type = file.type;
async function getFileFromFileEntry(fileEntry) {
try {
return await new Promise((resolve, reject) =>
fileEntry.file(resolve, reject)
);
} catch (err) {
console.log(err);
}
}
},
function(e) {
console.error(e);
}
);
});
});
// here uploadFileDetails is simller to what I declared at the top ;)
// I wan't this to be populated with file properties
// console.log(uploadFileDetails.name) --> //''
const uploadUrl = await this.getUploadUrl(uploadFileDetails);
const response: any = this.uploadFile(
uploadFileDetails,
uploadUrl
);
response
.then(function(success) {
console.log({ success });
this.presentToast('File uploaded successfully.');
this.loadFiles();
})
.catch(function(error) {
console.log({ error });
});
}
even though I can console.log the file in log 01. I am unable to get file properties like, size, name, type out of the resolveLocalFileSystemURL function. basically, I am unable to populate uploadFileDetails object. What am I doing wrong? Thank you in advance.
you actually need 4 Ionic Cordova plugins to upload a file after getting all the metadata of a file.
FileChooser
Opens the file picker on Android for the user to select a file, returns a file URI.
FilePath
This plugin allows you to resolve the native filesystem path for Android content URIs and is based on code in the aFileChooser library.
File
This plugin implements a File API allowing read/write access to files residing on the device.
File Trnafer
This plugin allows you to upload and download files.
getting the file's metadata.
file.resolveLocalFilesystemUrl with fileEntry.file give you all the metadata you need, except the file name. There is a property called name in the metadata but it always contains value content.
To get the human readable file name you need filePath. But remember you can't use returning file path to retrieve metadata. For that, you need the original url from fileChooser.
filePathUrl.substring(filePathUrl.lastIndexOf('/') + 1) is used to get only file name from filePath.
You need nativeURL of the file in order to upload it. Using file path returning from filePath is not going to work.
getFileInfo(): Promise<any> {
return this.fileChooser.open().then(fileURI => {
return this.filePath.resolveNativePath(fileURI).then(filePathUrl => {
return this.file
.resolveLocalFilesystemUrl(fileURI)
.then((fileEntry: any) => {
return new Promise((resolve, reject) => {
fileEntry.file(
meta =>
resolve({
nativeURL: fileEntry.nativeURL,
fileNameFromPath: filePathUrl.substring(filePathUrl.lastIndexOf('/') + 1),
...meta,
}),
error => reject(error)
);
});
});
});
});
}
select a file from the file system of the mobile.
async selectAFile() {
this.getFileInfo()
.then(async fileMeta => {
//get the upload
const uploadUrl = await this.getUploadUrl(fileMeta);
const response: Promise < any > = this.uploadFile(
fileMeta,
uploadUrl
);
response
.then(function(success) {
//upload success message
})
.catch(function(error) {
//upload error message
});
})
.catch(error => {
//something wrong with getting file infomation
});
}
uploading selected file.
This depends on your backend implementation. This is how to use File Transfer to upload a file.
uploadFile(fileMeta, uploadUrl) {
const options: FileUploadOptions = {
fileKey: 'file',
fileName: fileMeta.fileNameFromPath,
headers: {
'Content-Length': fileMeta.size,
'Content-Type': fileMeta.type,
},
httpMethod: 'PUT',
mimeType: fileMeta.type,
};
const fileTransfer: FileTransferObject = this.transfer.create();
return fileTransfer.upload(file.path, uploadUrl, options);
}
hope it helps. :)

Uploading base64 encoded Image to Amazon S3 via Node.js

Yesterday I did a deep night coding session and created a small node.js/JS (well actually CoffeeScript, but CoffeeScript is just JavaScript so lets say JS) app.
what's the goal:
client sends a canvas datauri (png) to server (via socket.io)
server uploads image to amazon s3
step 1 is done.
the server now has a string a la
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACt...
my question is: what are my next steps to "stream"/upload this data to Amazon S3 and create an actual image there?
knox https://github.com/LearnBoost/knox seems like an awesome lib to PUT something to S3, but what I'm missing is the glue between the base64-encoded-image-string and actual upload action?
Any ideas, pointers and feedback welcome.
For people who are still struggling with this issue. Here is the approach I used with native aws-sdk :
var AWS = require('aws-sdk');
AWS.config.loadFromPath('./s3_config.json');
var s3Bucket = new AWS.S3( { params: {Bucket: 'myBucket'} } );
Inside your router method (ContentType should be set to the content type of the image file):
var buf = Buffer.from(req.body.imageBinary.replace(/^data:image\/\w+;base64,/, ""),'base64')
var data = {
Key: req.body.userId,
Body: buf,
ContentEncoding: 'base64',
ContentType: 'image/jpeg'
};
s3Bucket.putObject(data, function(err, data){
if (err) {
console.log(err);
console.log('Error uploading data: ', data);
} else {
console.log('successfully uploaded the image!');
}
});
s3_config.json file :
{
"accessKeyId":"xxxxxxxxxxxxxxxx",
"secretAccessKey":"xxxxxxxxxxxxxx",
"region":"us-east-1"
}
Here's the code from one article I came across, posting below:
const imageUpload = async (base64) => {
const AWS = require('aws-sdk');
const { ACCESS_KEY_ID, SECRET_ACCESS_KEY, AWS_REGION, S3_BUCKET } = process.env;
AWS.config.setPromisesDependency(require('bluebird'));
AWS.config.update({ accessKeyId: ACCESS_KEY_ID, secretAccessKey: SECRET_ACCESS_KEY, region: AWS_REGION });
const s3 = new AWS.S3();
const base64Data = new Buffer.from(base64.replace(/^data:image\/\w+;base64,/, ""), 'base64');
const type = base64.split(';')[0].split('/')[1];
const userId = 1;
const params = {
Bucket: S3_BUCKET,
Key: `${userId}.${type}`, // type is not required
Body: base64Data,
ACL: 'public-read',
ContentEncoding: 'base64', // required
ContentType: `image/${type}` // required. Notice the back ticks
}
let location = '';
let key = '';
try {
const { Location, Key } = await s3.upload(params).promise();
location = Location;
key = Key;
} catch (error) {
}
console.log(location, key);
return location;
}
module.exports = imageUpload;
Read more: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property
Credits: https://medium.com/#mayneweb/upload-a-base64-image-data-from-nodejs-to-aws-s3-bucket-6c1bd945420f
ok, this one is the answer how to save canvas data to file
basically it loos like this in my code
buf = new Buffer(data.dataurl.replace(/^data:image\/\w+;base64,/, ""),'base64')
req = knoxClient.put('/images/'+filename, {
'Content-Length': buf.length,
'Content-Type':'image/png'
})
req.on('response', (res) ->
if res.statusCode is 200
console.log('saved to %s', req.url)
socket.emit('upload success', imgurl: req.url)
else
console.log('error %d', req.statusCode)
)
req.end(buf)
The accepted answer works great but if someone needs to accept any file instead of just images this regexp works great:
/^data:.+;base64,/
For laravel developers this should work
/* upload the file */
$path = Storage::putFileAs($uploadfolder, $uploadFile, $fileName, "s3");
make sure to set your .env file property before calling this method

Categories