Only showing results from stackoverflow.com

Had the exact same issue today, so I'll provide an answer in TypeScript(3.7.5) based on what worked out for me.

Tips:

  • FileAPI needs a Blob to work with (as others have also stated), it won't work with a file path.

The function:

static async createFile(path: string, name: string, type: string): Promise<File> {
            let response = await fetch(path);
            let data = await response.blob();
            let metadata = {
                type: type
            };
            return new File([data], name, metadata);
}

The call:

await createFile('../assets/images/someInterestingPNGImage.png', 'iAmAFile.png', 'image/png')
        .then((file) => {
            //do something with ur file.
            console.log(file);
         });
Answer from apfel on Stack Overflow
Top answer
1 of 1
3

Sources

For a JavaScript solution for either client-side or server-side, you can use Node.js; however,

  • client side requires a package called: "NWJS" available here: http://nwjs.io/
  • server side only requires "Node.js" available here: https://nodejs.org

You can find extensive documentation on either of these "JavaScript" solutions; however, there are other "JavaScript" solutions available, NodeJS is very popular.

If you work with another language on the server, like PHP, you can find more info about it here: http://php.net



Solution

The following describes a JavaScript solution with code for server-side that you can just copy & paste and modify to your needs.

This assumes you are running NodeJs on Linux and that the file/folder (path) is not recursive. The example below is not tested, feel free to test & fix as necessary.

For the client-side code interacting with the "server-side" example below, create an HTML form that uses: method="PUT" and the fields as required by the vars; -OR- use an AJAX method to accomplish the same.

Server-side: NodeJS

let http = require('http');
//File System package...
let fsys = require('fs');


let makePath = function(root, path, data)
{
    try
    {
        fsys.accessSync(root, fsys.W_OK);
    }
    catch(err)
    {
        return {code:403, text:'Forbidden'}
    }

    path = ((path[0] == '/') ? path.substr(1, path.length) : path);

    if (path.split('/').length > 2)
    { return {code:412, text:'Precondition Failed'}; }

    if (fsys.existsSync(path))
    { return {code:409, text:'Conflict'}; }

    if (path[path.length -1] == '/')
    { fsys.mkdirSync(root +'/'+ path.substr(0, path.length -2)); }
    else
    { fsys.writeFileSync((root +'/'+ path), (data || ' '), 'utf8'); }

    return {code:200, text:'OK'};
};


http.createServer
(
    function(request, response)
    {
        let vars = url.parse(request.url);

        if (path && (path.indexOf('/') > -1) && (request.method == 'PUT'))
        {
            var resp = makePath(__dirname, vars.path, vars.data);

            response.statusCode = resp.code;
            response.setHeader('Content-Type', 'text/plain');
            response.end(resp.text);
        }
    }
).listen(8124);

Usage

You can access this from your web browser, if your server runs on the same machine, in your web-browser's address bar type: http://127.0.0.1:8124 and hit enter/return; however, please see the proper NodeJS documentation for serving the necessary client-side HTML & JavaScript as mentioned.

🌐
Stack Overflow
stackoverflow.com › questions › 61937031 › how-do-i-get-file-path-for-image-in-a-hidden-folder
javascript - How do I get file path for image in a hidden folder? - Stack Overflow
@rkafds dots for a relative path should be before the forward slash, not after (so instead try <img src="../img/secretImage.png">) 2020-05-21T17:02:50.89Z+00:00
🌐
Stack Overflow
stackoverflow.com › questions › 22037443 › create-a-file-in-javascript
Create a file in javascript - Stack Overflow
I want to create a text file in javascript. I have tried this, but it doesn't work: var file_name=dir+'/aaa.txt'; var fso = CreateObject('Scripting.FileSystemObject'); var s = fsoo.CreateTextFile(
Find elsewhere
Top answer
1 of 1
4

I want to write file in user directory

You cannot directly write file to user filesystem .

After searching SO for similar Questions to accurately resolve Question, was able to $ cat contents of file created at plnkr following this answer posted by @Iain at Where does PERSISTENT file system storage store with chrome? . The file was written to the user filesystem at ~/.config/[chrome, chromium] directory.

Used file manager to navigate to

  ~/.config/[chrome, chromium]/Default/File System

to review the directory; the file containing text written below, was found in a folder having two digits as a folder name, then within two further sub-directories; a sub-directory having a single lowercase letter as folder name; within this sub-directory there was another sub-directory having two digits as a folder name; the file that was written by window.webkitRequestFileSystem had eight digits as a file name, without an extension, though having correct "text/plain" MIME type; set at Blob type property.

Then at terminal

  $ cd ~/.config/[chrome, chromium]/Default/File\ System/[three digits]/[lowercase letter]/[two digits]

  $ cat [eight digits]
  Lorem Ipsum

Have not tried to create a .sh file and execute it. Would probably require placing the directory in path or moving the file to a folder in existing path; set appropriate permissions for file. Could possibly adjust this at chrome / chromium browser settings, though have not tried this either.

You could probably write a command to copy or move the file at /path/to/file to an folder in path, and execute the file; or other approach.


You can use download attribute of a element to allow download of file created by createWriter to user filesystem.

The file system is sandboxed

Because the file system is sandboxed, a web app cannot access another app's files. You also cannot read or write files to an arbitrary folder (for example, My Pictures and My Documents) on the user's hard drive.

see also at Definititons

persistent storage Persistent storage is storage that stays in the browser unless the user expunges it or the app deletes it.
temporary storage Transient storage is available to any web app. It is automatic and does not need to be requested, but the browser can delete the storage without warning.


I want to write file in user directory because it has to be user understandable.

Edit, Updated

You can use the method described above. That is, use a file manager at to review how the folders and files appear in

  ~/.config/[chrome, chromium]/Default/File System

  ## do stuff with contents of file written by `window.requestFilesystem`

To view file in chrome / chromium FileSystem you can navigate to DevTools -> Experiments -> check FileSystem inspection , log.txt should be listed at Resources tab at FileSystem .

Can also navigate to file at address bar using URL

filesystem:http://run.plnkr.co/temporary/log.txt

which should have contents

Lorem Ipsum

or

filesystem:http://run.plnkr.co/temporary/

to view all files and directories in root of temporary filesystem

See Exploring the FileSystem API

First launch chrome / chromium with --allow-file-access-from-files flag , see How do I make the Google Chrome flag "--allow-file-access-from-files" permanent? .

Next

window.requestFileSystem  = window.requestFileSystem 
                            || window.webkitRequestFileSystem;

add error handling

function errorHandler(e) {
  var msg = '';

  switch (e.message) {
    case FileError.QUOTA_EXCEEDED_ERR:
      msg = 'QUOTA_EXCEEDED_ERR';
      break;
    case FileError.NOT_FOUND_ERR:
      msg = 'NOT_FOUND_ERR';
      break;
    case FileError.SECURITY_ERR:
      msg = 'SECURITY_ERR';
      break;
    case FileError.INVALID_MODIFICATION_ERR:
      msg = 'INVALID_MODIFICATION_ERR';
      break;
    case FileError.INVALID_STATE_ERR:
      msg = 'INVALID_STATE_ERR';
      break;
    default:
      msg = 'Unknown Error';
      break;
  };

  console.log('Error: ' + msg);
}

You should then be able to

function writeFile(fs) {

  fs.root.getFile('log.txt', {create: true}, function(fileEntry) {

    // Create a FileWriter object for our FileEntry (log.txt).
    fileEntry.createWriter(function(fileWriter) {

      fileWriter.onwriteend = function(e) {
        console.log('Write completed.');
        // call `readFile` here
        window.requestFileSystem(window.TEMPORARY, 1024*1024, readFile, errorHandler);

      };

      fileWriter.onerror = function(e) {
        console.log('Write failed: ' + e.toString());
      };

      // Create a new Blob and write it to log.txt.
      var blob = new Blob(['Lorem Ipsum'], {type: 'text/plain'});

      fileWriter.write(blob);

    }, errorHandler);

  }, errorHandler);

}

window.requestFileSystem(window.TEMPORARY, 1024*1024, writeFile, errorHandler);

function readFile(fs) {

  fs.root.getFile('log.txt', {}, function(fileEntry) {

    // Get a File object representing the file,
    // then use FileReader to read its contents.
    fileEntry.file(function(file) {
       var reader = new FileReader();

       reader.onloadend = function(e) {
         console.log(e.target.result)
       };

       reader.readAsText(file);
    }, errorHandler);

  }, errorHandler);

}

plnkr http://plnkr.co/edit/EVVNYYUvHiM545T06kMC?p=preview


Note, at Chrome 38+ it is also possible to create a File object using the new File() constructor; see Chrome: Create file input from blob with Javascript? .

No, It is background process, save the data into the file exist in folder.

This approach, too, will not automatically write created file to an existing folder at user filesystem.

With either approach user action should be required to save file to user filesystem. This can be achieved using download attribute at a element , data URI How to export JavaScript array info to csv (on client side)? , or an iframe element Download File Using Javascript/jQuery ; which should prompt user to either select to save file or not save file.


See also The FileSaver interface , FileSaver.js

Top answer
1 of 3
2

This should work in recent versions of Node.js:

import fs from "fs";
import { Blob } from "buffer";

let buffer = fs.readFileSync("./your_file_name");
let blob = new Blob([buffer]);
2 of 3
1

Here is how you can upload a file from the drive to Firebase Storage:

let bucket = admin.storage().bucket();
let uploadRes = await bucket.upload(filePath, options);

You can find a description of the option in the google cloud storage docs. You will most likely create a key in the google cloud console with permissions and export the file as a json. You will find this in the Google Cloud Platform console -> IAM & admin -> Service accounts -> Create service account (create it with a key). Once you exported the json, set the environment variable like this:

export GOOGLE_APPLICATION_CREDENTIALS='./the_exported_file.json'

PLEASE STORE THIS FILE SECURELY ON YOUR SERVER AS IT HAS READ AND WRITE ACCESS!

Below is a full example of an upload function that also saves the file under it's hash name.

<!-- language: typescript -->
import admin from "firebase-admin";
import path from 'path'
const sha256File = require('sha256-file');

const firebaseConfig = {
     apiKey: "...",
     authDomain: "abc.firebaseapp.com",
     databaseURL: "https://abc.firebaseio.com",
     projectId: "abc",
     storageBucket: "abc.appspot.com",
     messagingSenderId: "123",
     appId: "1:123:web:xxx",
     measurementId: "G-XXX"
};

admin.initializeApp(firebaseConfig);

async function uploadFile(filePath: string, uploadFolder: string, contentType: string, hash: string | undefined = undefined,)
    : Promise<string> {

    if (!hash) {
        hash = await sha256File(filePath);
    }
    let bucket = admin.storage().bucket();
    const ext = path.extname(filePath);
    const uploadPath = uploadFolder + hash + ext;
    const options = {destination: uploadPath};
    console.debug("starting upload");
    let uploadRes = await bucket.upload(filePath, options);
    console.debug("finished upload");

    let newMetadata = {
        contentType: contentType
    };
    if(uploadRes) {
        let file = uploadRes[0];
        file.setMetadata(newMetadata).then(() => {
            // Updated metadata for 'images/forest.jpg' is returned in the Promise
        }).catch(function (error) {
            console.error(error)
        });
    }

    return uploadPath;
}
Top answer
1 of 5
4

For those that are looking for a solution to this problem, I created an npm package to make it easier to retrieve files using Node's file system and convert them to JS File objects:

https://www.npmjs.com/package/get-file-object-from-local-path

This solves the lack of interoperability between Node's fs file system (which the browser doesn't have access to), and the browser's File object type, which Node cannot create.

3 steps are required:

  1. Get the file data in the Node instance and construct a LocalFileData object from it
  2. Send the created LocalFileData object to the client
  3. Convert the LocalFileData object to a File object in the browser.
// Within node.js
const fileData = new LocalFileData('path/to/file.txt')

// Within browser code
const file = constructFileFromLocalFileData(fileData)
2 of 5
2

I searched for File Systems examples and other possibilities and found nothing.

So I decide to create my own File object with JSON.

  var imagePath = path.join('/images/logo.png', 'logo.png');
    
  if (fs.statSync(imagePath)) {
     var bitmap = fs.readFileSync(imagePath);
     var bufferImage = new Buffer(bitmap);
    
     Magic = mmm.Magic;
     var magic = new Magic(mmm.MAGIC_MIME_TYPE);
     magic.detectFile(imagePath, function(err, result) {
          if (err) throw err;
          datas = [{"buffer": bufferImage, "mimetype": result, "originalname": path.basename(imagePath)}];
          var JsonDatas= JSON.parse(JSON.stringify(datas));
          log.notice(JsonDatas);
     });
 }

The output :

{ 
  buffer:
  { 
    type: 'Buffer',
    data:
    [ 
      255,
      216,
      255
      ... 24908 more items,
      [length]: 25008 
    ] 
  },
  mimetype: 'image/png',
  originalname: 'logo.png' 
}

I think is probably not the best solution, but it give me what I want. If you have a better solution, you are welcome to suggest it.

Top answer
1 of 16
2223

For individual dirs:

var fs = require('fs');
var dir = './tmp';

if (!fs.existsSync(dir)){
    fs.mkdirSync(dir);
}

Or, for nested dirs:

var fs = require('fs');
var dir = './tmp/but/then/nested';

if (!fs.existsSync(dir)){
    fs.mkdirSync(dir, { recursive: true });
}
2 of 16
244

No, for multiple reasons.

  1. The path module does not have an exists/existsSync method. It is in the fs module. (Perhaps you just made a typo in your question?)

  2. The documentation explicitly discourage you from using exists.

    fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.

    In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.

    Since we're talking about a directory rather than a file, this advice implies you should just unconditionally call mkdir and ignore EEXIST.

  3. In general, you should avoid the *Sync methods. They're blocking, which means absolutely nothing else in your program can happen while you go to the disk. This is a very expensive operation, and the time it takes breaks the core assumption of node's event loop.

    The *Sync methods are usually fine in single-purpose quick scripts (those that do one thing and then exit), but should almost never be used when you're writing a server: your server will be unable to respond to anyone for the entire duration of the I/O requests. If multiple client requests require I/O operations, your server will very quickly grind to a halt.


    The only time I'd consider using *Sync methods in a server application is in an operation that happens once (and only once), at startup. For example, require actually uses readFileSync to load modules.

    Even then, you still have to be careful because lots of synchronous I/O can unnecessarily slow down your server's startup time.


    Instead, you should use the asynchronous I/O methods.

So if we put together those pieces of advice, we get something like this:

function ensureExists(path, mask, cb) {
    if (typeof mask == 'function') { // Allow the `mask` parameter to be optional
        cb = mask;
        mask = 0o744;
    }
    fs.mkdir(path, mask, function(err) {
        if (err) {
            if (err.code == 'EEXIST') cb(null); // Ignore the error if the folder already exists
            else cb(err); // Something else went wrong
        } else cb(null); // Successfully created folder
    });
}

And we can use it like this:

ensureExists(__dirname + '/upload', 0o744, function(err) {
    if (err) // Handle folder creation error
    else // We're all good
});

Of course, this doesn't account for edge cases like

  • What happens if the folder gets deleted while your program is running? (assuming you only check that it exists once during startup)
  • What happens if the folder already exists, but with the wrong permissions?
🌐
Stack Overflow
stackoverflow.com › questions › 26362675 › javascript-extendscript-retrieve-a-folder-path-from-a-variable-create-a-ne
JavaScript + ExtendScript | retrieve a folder path from a variable & create a new folder inside - Stack Overflow
var targetFolder = Folder.selectDialog("Select a folder"); This is what I have. Now I need to retrieve the path to the selected folder and create a subfolder inside. I know how to create a folder