Save json+image files to disk and to express-server with fetch

Coding is not easy.
So when I find a solution to a problem I like to share it.
Here some options on how to save json+image files to disk and to express-server with fetch.

let my_json = {
"a": 1,
"b": 2,
"c": 3 
} 

function saveMyStuff(){
 saveJsonToDisk(my_json, newFileName+'.json', 'text/plain');
 uploadJson(my_json,newFileName+'.json','text/plain','aJson');

saveImgToDisk(oneSnapShot, fileName, 'image/png')
uploadImageArray(snapShotArray, newFileName,'aImage');
}

and here are the function that do the disk or server saving:


function saveJsonToDisk(content, fileName, contentType) {
    console.log("download() "+ fileName);

    var myJson = JSON.stringify(webVTT_json,null,'\t');

    var a = document.createElement("a");
    var jsonBlob = new Blob([myJson], {type: contentType});

    a.href = URL.createObjectURL(jsonBlob);
    a.download = fileName;

    a.click();
    URL.revokeObjectURL(a.href);
}

function uploadJson(content, fileName, contentType, filter) {

    console.log("postFiles "+fileName + " filter "+filter);

    var myJson = JSON.stringify(webVTT_json,null,'\t');

    var jsonBlob = new Blob([myJson], {type: contentType});


    const file = new File([jsonBlob], fileName);

    var formdata = new FormData();
    formdata.append(filter, file, file.name);
    // formdata.append('aImage', file, file.name);

    fetch(getSaveUrl(), {
        method: 'POST',
        enctype: "multipart/form-data",
        body: formdata,
    })
        .then(response => response.json())
        .then(result => {
        console.log('Success:', result);
    })
        .catch(error => {
        console.error('Error:', error);
    });

}

async function uploadImageArray(content, fileName, filter) {
    console.log("postFiles "+fileName + " filter "+filter);

    var formdata = new FormData();

    //https://stackoverflow.com/questions/48485656/wait-until-canvas-toblob-has-finished
    //https://stackoverflow.com/questions/46256630/how-to-get-multiple-image-file-infos-using-promise-in-javascript

    //we first need convert the images in the content array to blob
    //this takes a bit of time and can not be done without using asyn
    //so we need to wait for this process to be done which is done by using promise

    var allImages = [];
    for (var i = 0; i < content.length; ++i) {
        var aFile = content[i];
        allImages.push(new Promise(function (resolve, reject) {

            console.log("push "+i);
            aFile.canvas.toBlob(function(blob) {
                // get content as blob
                //            console.log("callback blob: " + blob);
                console.log("resolve "+i);
                resolve(blob);
            }, "image/png", 1.0);

        }));
    }

    //once all promises are fulfilled can be convert the blobs to a file
    //and then add them to the formdata
    //formadata in this care will hold many image
    Promise.all(allImages).then(function(blobs){
        console.log("dims.length "+blobs.length) // [] array,I expect [23,434,123]...

        for (var i = 0; i < blobs.length; ++i) {
            var file = new File([blobs[i]],  newFileName+"_"+pad(i,3)+".png");

            formdata.append(filter, file, file.name);
        }

        const response = fetch(getSaveUrl(), {
            method: 'POST',
            enctype: "multipart/form-data",
            body: formdata,
        });

        console.log(response);

    }).catch(function(errdims){
        console.log(errdims)
    });
}



function saveImgToDisk(content, fileName, contentType) {
    console.log("download() "+ fileName);

    var anchor = document.createElement("a");
    anchor.href = URL.createObjectURL(content);
    anchor.download = fileName;

    anchor.click();
    URL.revokeObjectURL(anchor.href);
}

function uploadOneImage(content, fileName, filter) {
    console.log("uploadImage "+fileName + " filter "+filter);


    var formdata = new FormData();
    content.canvas.toBlob(function(blob) {
        // get content as blob
        var file = new File([blob], fileName+".png");
        formdata.append(filter, file, file.name);

        fetch(getSaveUrl(), {
            method: 'POST',
            enctype: "multipart/form-data",
            body: formdata,
        })
            .then(response => response.json())
            .then(result => {
            console.log('Success:', result);
        })
            .catch(error => {
            console.error('Error:', error);
        });


    }, "image/png", 1.0);
}

here is the contented server.js, which is the script running on the server or also on your local server:

var express = require('express')
var multer  = require('multer')
var upload = multer({ dest: 'uploads/' })

var bodyParser = require('body-parser')
var morgan = require('morgan')
var crypto = require('crypto')
var cors = require('cors')
var mime = require('mime')
var path = require('path')

const fs = require('fs'); //use the file system so we can save files

var app = express()


var trackStorage = multer.diskStorage({
    destination: function (req, file, callback) {
        //    callback(null, '/tmp/my-uploads')
        callback(null, 'upload_myFiles');
    },
    filename: function (req, file, callback) {
        //            callback(null, file.fieldname + '-' + Date.now()+ '.' + path.extname(file.originalname));
        callback(null, file.originalname);


    }
})

app.use(cors())
app.options('*', cors()) // include before other routes

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan('dev'));

//serve out any static files in our public HTML folder
app.use(express.static('public'))
app.use(express.static('upload_myFiles'));

//makes the app listen for requests on port 3000
app.listen(9001, function(){
    console.log("app listening on port 9001!")
})

var upload = multer({
    storage: trackStorage,
     limits: {
        fileSize: 2 * 1024 * 1024 * 1024 //2MB max file(s) size
    }
});

var cpUpload = upload.fields([{ name: 'aJson', maxCount: 1 }, { name: 'aImage', maxCount: 100 }]);

app.post('/uploadFile', cpUpload, function (req, res, next) {
    // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
    //
    // e.g.
    //  req.files['avatar'][0] -> File
    //  req.files['gallery'] -> Array
    //
    // req.body will contain the text fields, if there were any

    if (!req.file) {
        console.log("No file received");
        return res.send({
            success: false
        });

    } else {
        console.log('file received');
        return res.send({
            success: true
        })
    }
})
3 Likes

Maybe the saveImgToDisk() function needs more work.
Might be better to use the standard p5js way to save images.
save(snapShot[i],"test_"+i+".png");

Can you clarify if this is a question of are you showcasing your approach.

If the former, please state the question clearly with a brief comment, error messages and description of observed vs intended behavior.

If the latter, tell us what it does and how to use it.

Kf

tough love :wink:
I made an addition to the original post.

More code to add to my list of way to save images.

This time I wanted to save image with a p5js electron app.

function mousePressed() {
 saveOneImage(capture.get(), "images/img_"+ currentFileName);
 saveOneCanvas("images/canvas_"+ currentFileName);
}
//https://stackoverflow.com/questions/52692258/how-to-save-an-image-drawn-on-the-canvas-in-electron-js/52701672
function saveOneImage(content, filePath) {
    console.log("saveCallback() "+ filePath);

    // Get the DataUrl from the Canvas
    //    const url = canvas.toDataURL('image/jpg', 0.8);
    const url = content.canvas.toDataURL('image/jpg', 1.0);
    // remove Base64 stuff from the Image
    const base64Data = url.replace(/^data:image\/png;base64,/, "");
    fs.writeFile(filePath, base64Data, 'base64', function (err) {
        console.log(err);
    });
}
function saveOneCanvas(filePath) {
    console.log("saveCallback() "+ filePath);

    // Get the DataUrl from the Canvas
    const url = canvas.toDataURL('image/jpg', 0.8);
    // remove Base64 stuff from the Image
    const base64Data = url.replace(/^data:image\/png;base64,/, "");
    fs.writeFile(filePath, base64Data, 'base64', function (err) {
        console.log(err);
    });
}
1 Like