0

I'm writing a program I need to query a database for values which are comprised of a url, and save them to an array. Then I need them to take the strings in that array and create and write files with the last characters of them after the last slash in the each of the names pulled from a result in the query.

The urls are like:

http://examplesite.com/wp-content/uploads/YYYY/MM/17818380_1556368674373219_6750790004844265472_n-1.jpg
http://examplesite.com/wp-content/uploads/YYYY/MM/17818380_1556368674373219_6750790004844265472_n.jpg
https://examplesite.com/wp-content/uploads/YYYY/MM/10643960_909727132375975_2074842458_n-44x55.jpg
http://examplesite.com/wp-content/uploads/YYYY/MM/10643960_909727132375975_2078842458_n-320x150.jpg

My starting code is:

const mysql = require('mysql');
const process = require('process');
const glob = require('glob');
const fs = require('fs');

function connectToDB() {
    return new Promise((resolve,reject)=>{
        try {
            var connection = mysql.createConnection({
                host:"10.1x.xxx.x",
                user: "username",
                password: "password",
                database: "mydb"
            });
        } catch(e) {
            reject(e);
        }
        if(!connection) {
            reject(new Error("No Connection"));
        }
        connection.connect(function(err) {
            if(err) reject(err);
            console.log("inside db")
            resolve(connection);
        });
    });
}

function getFilesToReplace(connection){
    return new Promise( (resolve, reject) =>  {
        var urls = [];       
        var query = "select fullURL from my_postmeta left outer join my_posts on (my_postmeta.post_id = my_posts.id) where my_postmeta.meta_key=\"_my_pichosting_url\" ";
        connection.query(query, function(err, result, fields){
            if(err) {
                reject(err);
            }
            for (var i in result) {
                urls.push(result[i].fullURL.toLowerCase());
            }
            resolve(urls);
        });
    });
}

However, when I get to the main function, which is below:

async function main(){

    try{
        var theSQLconnection = await connectToDB();
    }
    catch(e){
        console.log('failed to connect');
        return;
    }

    try{
        var urlsfromdb = await getFilesToReplace(theSQLconnection);

    }
    catch(err){
        console.log('more problems: ', e)
        return;
    }
    theSQLconnection.end();

    console.log(urlsfromdb.length);

    try{
        for(var i = 0; i < urlsfromdb.length; i++){

            var filecontent = `${urlsfromdb[i]}`;
            fs.writeFile(`../../wp-content/uploads/newfolder/`, filecontent, function(err){
                if(err){
                    return console.log("error overwriting .jpg file: ", err)
                }
            })
        }


    }
    catch(e){
        console.log(`error: ${e}`)
    }
}

I get an error, namely:

error overwriting .jpg file: { [Error: EISDIR: illegal operation on a directory, open '../../wp-content/uploads/newfolder/'] errno: -21, code: 'EISDIR', syscall: 'open', path: '../../wp-content/uploads/scriptdeletedir/' }

Why am I getting this error? I want in new folder, to be files like 10643960_909727132375975_2078842458_n-320x150.jpg, etc.

Lelio Faieta
  • 6,457
  • 7
  • 40
  • 74
AviG
  • 362
  • 2
  • 14

1 Answers1

0

The main problem is here:

fs.writeFile(`../../wp-content/uploads/newfolder/`, filecontent, function(err){
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
    if(err){
        return console.log("error overwriting .jpg file: ", err)
    }
})

You haven't provided a filename for the file to write. That's why you're getting an error trying to write to a directory. You'll need to supply a filename.


FWIW, there are a few other things worth pointing out:

  1. If an error is thrown during the call to the promise executor function (the function you pass into new Promise), the promise is rejected with that error, so you don't need the try/catch blocks you have in the promise executor in connectToDB.

  2. There's no reason to declare urls outside the query callback in getFilesToReplace.

  3. You can create the array of URLs you want to return via map in the query callback.

  4. for-in isn't meant for looping through arrays. See my answer here for your many and varied options. In modern code, usually for-of is your best bet.

  5. In modern code, it's best to use let or const, not var.

  6. There's no point to the template literal in this line:

    var filecontent = `${urlsfromdb[i]}`;
    

    unless you're trying to implicitly convert urlsfromdb[i] to string (and if you were, String(urlsfromdb[i]) would be clearer). Since you know those are already strings, there's no need for conversion:

    var filecontent = urlsfromdb[i];
    
  7. reject(err); will reject the promise, but it doesn't terminate the function it's in, all statements following it will also run. So for instance, this code:

    connection.connect(function(err) {
        if(err) reject(err);
        console.log("inside db")
        resolve(connection);
    });
    

    will always log "inside db", even if there's an error and it's rejected the promise.

So for instance:

const mysql = require('mysql');
const process = require('process');
const glob = require('glob');
const fs = require('fs');

function connectToDB() {
    return new Promise((resolve,reject)=>{
        // *** Removed unnecessary `try`/`catch`es
        // *** Used `const` instead of `var`
        const connection = mysql.createConnection({
            host:"10.1x.xxx.x",
            user: "username",
            password: "password",
            database: "mydb"
        });
        if(!connection) {
            reject(new Error("No Connection"));
        }
        connection.connect(function(err) {
            // *** Used `else` for non-error logic
            if(err) {
                reject(err);
            } else {
                console.log("inside db")
                resolve(connection);
            }
        });
    });
}

function getFilesToReplace(connection){
    return new Promise( (resolve, reject) =>  {
        // *** Removed `urls`, used `const` instead of `var`
        const query = "select fullURL from my_postmeta left outer join my_posts on (my_postmeta.post_id = my_posts.id) where my_postmeta.meta_key=\"_my_pichosting_url\" ";
        connection.query(query, function(err, result, fields){
            // *** Added `else` for non-rejection path
            if(err) {
                reject(err);
            } else {
                // *** Used `map` (and destructuring) to build the result
                resolve(result.map(({fullURL}) => fullURL.toLowerCase());
            }
        });
    });
}

async function main(){
    // *** Used `errorPrefix`, a single `try`/`catch`, and `const`
    let errorPrefix = "failed to connect";
    try{
        const theSQLconnection = await connectToDB();
        errorPrefix = "failed to get files";
        const urlsfromdb = await getFilesToReplace(theSQLconnection);
        errorPrefix = "error";
        theSQLconnection.end();

        console.log(urlsfromdb.length);

        // *** Used `for-of` and `const`
        for (const filecontent of urlsfromdb) {
            fs.writeFile(`../../wp-content/uploads/newfolder/${/* you need a filename here */}`, filecontent, function(err){
                if(err){
                    return console.log("error overwriting .jpg file: ", err)
                }
            })
        }
    }
    catch(e){
        console.log(`${errorPrefix}: ${e}`)
    }
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • now, when writing the file names, how can I use a regex to write the file names to account for the types of URLS I gave above, where some are http and some https? – AviG Mar 18 '20 at 19:37
  • @AviG - That's a different question. You'd probably do something like `http(?:s?)`, which is `http` followed by a non-capturing group with an optional `s`. But if you need more regex help, best to post a question about the regex. – T.J. Crowder Mar 18 '20 at 19:55
  • I have this question; https://stackoverflow.com/questions/60714883/how-can-i-use-regexes-in-javascript-to-chop-part-of-a-url-without-specifying-fix/60714944#60714944 could be you so kind as to look? Thanks! – AviG Mar 18 '20 at 19:58