Copy byte array into clipboard - c#

I'm trying to do a client-server program in which it is possible to share the content of the clipboard.
Right now I am able to share it if the content type is audio, image or text.
The idea is that I convert the content in a byte array, send it, convert it back in its original type (Stream, BitmapSource or string) and inject it in the client clipboard by using the methods Clipboard.SetAudio, Clipboard.SetImage or Clipboard.SetText.
My problem is when there are some files in the clipboard. I use the method Clipboard.GetFileDropList to get a list of the files, and for each file in the list I convert it in a byte array and send it to the client. How can I inject this byte array in the client clipboard?
I know there is the method Clipboard.SetFileDropList, but it requires me to provide a file list and since the file does not exist on the client I cannot use it.
How can I solve this problem?

In order to make the client treat the files as pastable, they'll need to exist on the client filesystem in some way, since the clipboard expects a list of filenames when setting clipboard content.
This can be done by transferring the data as a stream to your client, and then making the client immediately unpack that stream to a temp folder, the path to which is obtainable via:
var temp = Environment.ExpandEnvironmentVariables("%TEMP%");
Once done and the files are i place, you can position those files on the clipboard as if they were the ones copied.
Be warned that supporting file copy/paste instead of having an option to "transfer" files could run much slower than other operations, due to how big files can get.

Related

Zipping a large amount of data into an output stream without loading all the data into memory first in C#

I have a C# program that generates a bunch of short (10 seconds or so) video files. These are stored in an azure file storage blob. I want the user to be able to download these files at a later date as a zip. However, it would take a substantial amount of memory to load the entire collection of video files into memory to create the zip. I was wondering if it is possible to pull data from a stream into memory, zip encode it, output it to another stream, and dispose of it before moving onto the next segment of data.
Lets say the user has generated 100 10mb videos. If possible, this would allow me to send the zip to the user without first loading the entire 1GB of footage into memory (or storing the entire zip in memory after the fact).
The individual videos are pretty small, so if I need to load an entire file into memory at a time, that is fine as long as I can remove it from memory after it has been encoded and transmitted before moving onto the next file
Yes, it is certainly possible to stream in files, not requiring even any of those to be entirely in memory at any one time, and to compress, stream out, and transmit a zip file containing those, without holding the entire zip file either in memory or mass storage. The zip format is designed to be streamable. However I am not aware of a library that will do that for you.
ZipFile would require saving the entire zip file before transmitting it. If you're ok with saving the zip file in mass storage (not memory) before transmitting, then use ZipFile.
To write your own zip streamer, you would need to generate the zip file format manually. The zip format is documented here. You can use DeflateStream to do the actual compression and Crc32 to compute the CRC-32s. You would transmit the local header before each file's compressed data, followed by a data descriptor after each. You would save the local header information in memory as you go along, and then transmit the central directory and end record after all of the local entries.
zip is a relatively straightforward format, so while it would take a little bit of work, it is definitely doable.

Pass byte array back to its original file from sql filestream

I have setup filestream on my mssql server, and it works pretty well thus far. Currently, I have one entity in my database, that I have added manually.
When I added my file, it was automatically converted to a byte[], which Similarly appears as a byte[] when I get it through my .NET Core application (surprise).
Optimally, I would like to know, how I can decode this byte array into the original file? I have read several places, that I need to provide the original extension of the file in order to do that.
However, I have not added such a column in my database - I could easily add such a column, but it seems odd to me, if it isn't possible to pass it back to its original format without providing additional parameters.
Therefore, is there a way, in which I can convert the byte array back to its original file so that the user easily can download it, without having to do some sort of comprehensive conversion?
I would happily like to know, if one of you can point me in a direction here.
A filestream column contains the file's contents, not its external metadata, like the original filename, extension, directory location and access control list. If you write the byte[] to disk with, eg, File.WriteAllBytes(string,byte[]) it will be a usable file.

Best way to split files into UDP packet sized chunks for peer to peer file sharing?

I'm working on a P2P file sharing program and in order to pass the files in small bits I need to split the uploaded file somehow.
Now, I've made a program that splits a file into small files and puts them in a folder using C# Stream class, and it can also rebuild it. However, it's inefficient and takes a lot of time. I thought of reading the data from the stream with an offset according to the requested file and then sending it without saving. However, I don't know how to add it to the receiving end at the right order as the data will not be sent in order.
On a side note, how does bitTorrent do that kind of functionality?
thanks
The receiver needs to store the chunks. The sender does not. Probably, you should create the entire file on the receiver zero initialized on disk. Then, you can fill in the holes as you receive them. You need a separate structure to track what ranges are there yet, for example a List<Tuple<int, int>>.

DotNetZip streaming

I'm trying to zip a bunch of files and make the data consumable via a stream.
I would like to keep the memory footprint as small as possible.
My idea was to implement a Stream where I've got a bunch of FileStream objects as data members. When the Read method on my Stream was called, I would read some data from one of my file streams and use the ZipOutputStream instance to write zipped data to temporary storage stream which i would then forward the read request to.
This temporary storage stream would just be a queue of bytes. As these bytes are moved into a buffer (via a call to Read), they'd be deleted from the queue. This way, I'd only be storing the bytes that haven't been read yet.
Unfortunately, it seems as though when i dispose a ZipOutputStream it needs to write in random file locations in order to create a valid zip file. This will prevent me from using my "fleeting data" solution.
Hopefully this is all clear :)
Is there another way to minimize memory footprint when creating zip files? Please Help!
Thanks!
ZipOutputStream doesn't need to write to random locations in the output stream (in other words, call Seek()). But if the stream you're writing into reports that it CanSeek, it will use that ability to update some headers.
So, make sure that the stream you're writing to returns false for CanSeek() and everything should work fine.

Display a file from a byte[] or stream

I've got a winforms app that stores the contents of files in a database. The stored files can be of just about any type (word, excel, PDF, text, image ...) the user can select just about any type of file to load.
The user can then query the database, find a file and then open it.
I've got no problems extracting the byte array from the database, as either a stream or a byte array.
Ideally I'd be able to display the file directly from a byte array or stream; at the moment I'm saving it as a temporary file and then opening that with:
Process.Start(fileName);
How can I display the file with the associated application either from any of the byte array or stream file?
In windows, your only option is to do exactly what you're doing. Outlook, Internet explorer, firefox, all do this
Maybe you want to research a little bit on Memory Mapped File.
you can try to open the directory containing it, but it will be the same thing you're doing right now.. if the associated app is known by the OS, then there will be no problem..
If you store a filename in the DB along with the byte stream, you can determine the file type from the extension. There's two options in this case:
Use the registry to determine what application to use. For more info on this, take a look at this conversation on bytes.com.
P/Invoke SHGetFileInfo to determine what application to use.
NB: With both options you'll still need to write the file data to a temp file on disk in order to load it.
Personally, I'd think what you're doing is probably the easiest option, anyway (unless you'd like to provide custom viewers for certain file-types, etc)

Categories

Resources