Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method to get/set file pointers in clipboard #9035

Open
darsain opened this issue Mar 27, 2017 · 54 comments
Open

Method to get/set file pointers in clipboard #9035

darsain opened this issue Mar 27, 2017 · 54 comments

Comments

@darsain
Copy link

darsain commented Mar 27, 2017

There is currently no mechanism to get/set file pointers from/to clipboard.

File pointers: The stuff in clipboard when you copy (ctrl+c) selected files in your OS file explorer.

After ~15 min research, there was #2244 issue which went a different direction and than got closed. Also there are some projects on hold waiting for this kind of functionality, such as bortexz/quercus#1.

@bompi88
Copy link

bompi88 commented Jun 7, 2017

EDIT: Not ideal, but on mac I think I've used something like:

var filePath = clipboard.read('public.file-url').replace('file://', '');

to retrieve the path of the copied file.

On windows:

var rawFilePath = clipboard.read('FileNameW');
var filePath = rawFilePath.replace(new RegExp(String.fromCharCode(0), 'g'), '');

@darsain darsain changed the title Method for retrieving file pointers from clipboard Method to get/set file pointers in clipboard Jun 7, 2017
@oe
Copy link

oe commented Jan 20, 2018

@bompi88 this works well! But I guess nobody know this, and can only get only one file's path if multi files are copied. There should be an API like clipboard.readPaths() return an array of copied files' path.

An additional API like clipboard.readFileMetas() return an array of copied files' meta info {lastModified, lastModifiedDate, name, path, size, type} would be better. @zcbenz

@timkendrick
Copy link

timkendrick commented Jan 20, 2018

@evecalm From inspecting the clipboard with Apple's clipboard viewer sample app, it looks like you should be able to get the path of multiple files via clipboard.read('NSFilenamesPboardType') (in plist format).

This doesn't help with setting the clipboard though, seeing as Electron only allows you to copy plain text to the clipboard (not e.g. NSFilenamesPboardType data).

It'd be great if there were some way to set non-plaintext clipboard data.

@timkendrick
Copy link

Actually, after further investigation, it looks like copying files to the clipboard programmatically is also totally possible (on macOS at least) using the experimental clipboard.writeBuffer() API:

clipboard.writeBuffer(
  'NSFilenamesPboardType',
  Buffer.from(`
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <array>
        <string>/path/to/file1.ext</string>
        <string>/path/to/file2.ext</string>
      </array>
    </plist>
  `)
)

@oe
Copy link

oe commented Jan 22, 2018

@timkendrick Awesome!

But I guess we need a much more developer-friendly api 😟

@timkendrick
Copy link

@evecalm you can use the plist npm package to simplify working with plist-formatted strings:

const plist = require('plist');

function hasClipboardFiles() {
  return electron.remote.clipboard.has('NSFilenamesPboardType');
}

function getClipboardFiles() {
  if (!hasClipboardFiles()) { return []; }
  return plist.parse(electron.remote.clipboard.read('NSFilenamesPboardType'));
}

function setClipboardFiles(filePaths) {
  electron.remote.clipboard.writeBuffer('NSFilenamesPboardType', Buffer.from(plist.build(filePaths)));
}

@bpasero
Copy link
Contributor

bpasero commented Feb 3, 2018

@bompi88 I tried to write on Windows to FileNameW but I could not get it to work, even if the contents match exactly what I get when I do the same from the Windows explorer. Reading seems fine, but has someone managed to write to the clipboard on Windows in a way that you can paste to the Windows explorer?

@bpasero
Copy link
Contributor

bpasero commented Feb 6, 2018

It looks like when writing to NSFilenamesPboardType on macOS, the renderer crashes/freezes when pasting into an input field right after.

@dengyaolong
Copy link
Contributor

how to get file paths in windows?

@oe
Copy link

oe commented Jun 13, 2018

@bpasero @dengyaolong

You may try this on Windows:

clipboard.readBuffer('FileNameW').toString('ucs2').replace(RegExp(String.fromCharCode(0), 'g'), '')

@lizhengnacl
Copy link

@evecalm

HIHI,if i copy multiple files at the same time, how can i get all the file list on windows?

@oe
Copy link

oe commented Jun 14, 2018

@lizhengnacl haven't found a way :(

@super-ienien
Copy link

+1

1 similar comment
@seiyata
Copy link

seiyata commented Dec 25, 2018

+1

@zinne
Copy link

zinne commented Apr 20, 2019

Actually, after further investigation, it looks like copying files to the clipboard programmatically is also totally possible (on macOS at least) using the experimental clipboard.writeBuffer() API:

clipboard.writeBuffer(
  'NSFilenamesPboardType',
  Buffer.from(`
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <array>
        <string>/path/to/file1.ext</string>
        <string>/path/to/file2.ext</string>
      </array>
    </plist>
  `)
)

great, thanks, works like a charm on MacOS

@talhaHavadar
Copy link

@evecalm

HIHI,if i copy multiple files at the same time, how can i get all the file list on windows?

I found a format name 'FileGroupDescriptorW' for this purpose that lists the names of the files. But I did not have enough time to format the output of clipboard.read function.

You can try to improve the regular expression in @bompi88 's answer.

var rawFilePath = clipboard.read("FileGroupDescriptorW");
var filePath = rawFilePath.replace(new RegExp(String.fromCharCode(0), 'g'), '');
console.log("Clipboard(RAW): ", rawFilePath);
console.log("Clipboard(File): ", filePath);

If you can parse the output correctly please share it with us. Have a good day!

@dbteku
Copy link

dbteku commented Sep 28, 2019

@evecalm
HIHI,if i copy multiple files at the same time, how can i get all the file list on windows?

I found a format name 'FileGroupDescriptorW' for this purpose that lists the names of the files. But I did not have enough time to format the output of clipboard.read function.

You can try to improve the regular expression in @bompi88 's answer.

var rawFilePath = clipboard.read("FileGroupDescriptorW");
var filePath = rawFilePath.replace(new RegExp(String.fromCharCode(0), 'g'), '');
console.log("Clipboard(RAW): ", rawFilePath);
console.log("Clipboard(File): ", filePath);

If you can parse the output correctly please share it with us. Have a good day!

I've been playing around with this code, and digging into Windows internals and this is what I found out.

I found the list of supported formats in windows here -> Formats

I did find the FileGroupDescriptorW format. However, it seems that the format only returns the short name of the file and not the full path.

If you dig deeper, their FieldDescriptor only has a the fileName and not the full path.

You can verify this functionality by using the code above. It prints out only the file names and not their full path. (Along with other garbage characters)

You can also verify this by going to powershell and typing Clipboard-Get -Format FileDropList.

There is one more format you can try as well. It seems that if you use this, it returns the full path but the encoding is all wonky as before. Try Shell IDList Array. The data seems bigger, but I'm not sure what data we are missing.

I mean you can keep going down the rabbit hole and see more info on clipboard transfering here. (On Windows)

If you dig deeper into the clipboard from the MSDN docs. It says that if you use CF_HDROP that you can get the list of files and their paths somehow. Unfortunately, I don't think there is a way that node can get it other than creating a windows only native module in C++ or Go and calling it from node. We might be able to if we figure out how to decode the data from the buffer correctly, but for now I think the best way would be a Native Module. If there are any experts on this, and the info I gathered is sending me in the wrong direction let me know. If you have any more information or know Native C++ development well, this could help a ton here.

@xland
Copy link
Contributor

xland commented Nov 12, 2019

How about this issue's progress?
I support this suggestion
@oe @bpasero

@bompi88 this works well! But I guess nobody know this, and can only get only one file's path if multi files are copied. There should be an API like clipboard.readPaths() return an array of copied files' path.

An additional API like clipboard.readFileMetas() return an array of copied files' meta info {lastModified, lastModifiedDate, name, path, size, type} would be better. @zcbenz

@shenlanchenwei
Copy link

Electron Clipboard, read the path of multiple copied files, still not solved?

@alex8088
Copy link

alex8088 commented Feb 4, 2021

my solution (macOS && windows) : https://github.com/alex8088/clipboard-files

support read or write file path for clipboard

@Nantris
Copy link
Contributor

Nantris commented Mar 19, 2021

Anybody know an equivalent to FileNameW and CF_HDROP for Linux systems?

@liyuzhao
Copy link

how to get file paths in linux?

@Nantris
Copy link
Contributor

Nantris commented Apr 23, 2021

@liyuzhao - if you figure it out, please do share. I spent some time trying, but never did succeed. It doesn't help that inspecting the buffer values in the clipboard is so damn difficult on Linux. On Windows/macOS there are great tools to explore all the formats contained in the clipboard, but not so on Linux.

@kenan2002
Copy link

I wrote a library for this issue with some additional clipboard image processing features. https://www.npmjs.com/package/electron-clipboard-ex

@FatShen3
Copy link

FatShen3 commented Sep 2, 2021

Hello everyone, after I upgrade to electron v13.1.7, clipboard.readBuffer('CD_HDROP') not work anymore while clipboard.readBuffer('FileNameW') works well. But I want to get all list of copy files, anyone same probleam ?

@Nantris
Copy link
Contributor

Nantris commented Sep 3, 2021

@FatShen3 for an issue like that you definitely need to specify to OS you're seeing the issue on.

@FatShen3
Copy link

@FatShen3 for an issue like that you definitely need to specify to OS you're seeing the issue on.

Windows 10 Pro 20H2 19042.1288. The current electron version i use is 13.1.8.

  • clipboard.readBuffer('FileNameW') works fine
  • clipboard.writeBuffer('FileNameW', param) can not write file path in system clipboard(I can not use paste in windows file explorer), but I can still use clipboard.readBuffer('FileNameW') to get filePath in electron
  • clipboard.readBuffer('CD_HDROP') and clipboard.writeBuffer('CD_HDROP') can not work, always return empty string

CD_HDROP can work perfectly in Electron V11

@Nantris
Copy link
Contributor

Nantris commented Oct 20, 2021

Huh, that's strange. What were you copying to populate CD_HDROP? I don't use readBuffer/writeBuffer except in fiddling around, but it seems for me like it's returning an empty Uint8Array no matter what I copy in Electron@11.x on Windows 7.

@FatShen3
Copy link

In the code blow, I can wrtie file to system clipboard in Electron V11, but it can not work in Electron V13

const filePaths = ['C:/1.txt', 'C:/2.txt']
const str = '\u0014\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0000' + filePaths.join('\u0000') + '\u0000\u0000'
        clipboard.writeBuffer('CD_HDROP', Buffer.from(str, 'ucs-2'))

In the code blow, I can get multiple filePaths from system clipboard in Electron V11, but it can not work in Electron V13

const winFileStr = clipboard.readBuffer('CD_HDROP').toString('ucs2')
        filePaths = winFileStr
          .replace(/\u0014\u0000{7}\u0001\u0000/, '')
          .split('\u0000') // split each filePath
          .filter(e => e) // still get some \u0000, ignore them
 // winFileStr is like  ['C:/1.txt', 'C:/2.txt']

@Nantris
Copy link
Contributor

Nantris commented Oct 21, 2021

Hm... I'm able to make that work in Windows 7 using that code. Does this Electron-Fiddle (of your own code) also fail for you on Windows 10 @FatShen3? https://gist.github.com/65d60ea177626fba9d7145b782a6a3d4

I assume it will fail for you, even though it works for me, and if so I think we'll need to find where this issue was introduced and flag down a maintainer.

@FatShen3
Copy link

Hm... I'm able to make that work in Windows 7 using that code. Does this Electron-Fiddle (of your own code) also fail for you on Windows 10 @FatShen3? https://gist.github.com/65d60ea177626fba9d7145b782a6a3d4

I assume it will fail for you, even though it works for me, and if so I think we'll need to find where this issue was introduced and flag down a maintainer.

Yes, it work in this way just in electron itself. But what i want is write file paths to system clipboard, if success, i can press ctrl + v to paste these files like ['C:/1.txt', 'C:/2.txt'] in file explorer ( or may be called windows explorer ? ) .

FYI. win32 Shell Clipboard Formats

@icheer
Copy link

icheer commented May 7, 2022

I wrote a library for this issue with some additional clipboard image processing features. https://www.npmjs.com/package/electron-clipboard-ex

This lib helps me out perfectly. Thanks a lot!

@ishowshao
Copy link

i try encodeURI to file path , it's ok

@ishowshao
Copy link

clipboard.writeBuffer('public.file-url', Buffer.from(`file://${encodeURI(filepath)}`, 'utf-8'));

@OldDream
Copy link

I wrote a library for this issue with some additional clipboard image processing features. https://www.npmjs.com/package/electron-clipboard-ex

Thank you ! This helps me a lot .

@minzhang2
Copy link

thanks

@samantrader
Copy link

this code donot work for me why ? and paste item on windows context menu donot enable

clipboard.writeBuffer('public.file-url', Buffer.from(file://${encodeURI(filepath)}, 'utf-8'));

@Howlcn1997
Copy link

on windows:
require('child_process').exec( chcp 65001;Get-Content -Encoding Byte ${require('iconv-lite').encode(path, 'utf8').toString()} | Set-Clipboard, { shell: 'powershell.exe' }, () => {} )
on mac:
require('electron').clipboard.writeBuffer('public.file-url', Buffer.from(file://${path}))

it works for me

@ARPHS
Copy link

ARPHS commented Nov 17, 2023

I wrote a library for this issue with some additional clipboard image processing features. https://www.npmjs.com/package/electron-clipboard-ex

Thank you very much. Your library has been a great help to me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.