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

Support Copying Files Via Drag 'n' Drop #9

Open
Reda-Beloued opened this issue Dec 9, 2021 · 3 comments
Open

Support Copying Files Via Drag 'n' Drop #9

Reda-Beloued opened this issue Dec 9, 2021 · 3 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@Reda-Beloued
Copy link

First of all, Thank you so much for this very useful piece of software especially because it is fully written in C#. For months, I was looking for an MVP that does this with no luck! and I was amazed to see this yesterday on HN

One request is, if possible to add copying files from the host PC by dragging and dropping them directly on the "p2p_desktop" window to have them copied to the guest PC (on its desktop or the active app's window)

@miroslavpejic85
Copy link
Owner

Hello @Reda-Beloued, thank you very much, yes of course, It would be a very nice feature to add.

@miroslavpejic85 miroslavpejic85 added the enhancement New feature or request label Dec 9, 2021
@miroslavpejic85 miroslavpejic85 added the good first issue Good for newcomers label Dec 18, 2021
@miroslavpejic85
Copy link
Owner

miroslavpejic85 commented Jul 26, 2022

We can create a new UdtSocket for a new connection to handle the File Transfer.

I leave a snippet to start/take inspiration from and a simple video on how to enable the drag & drop on the PictureBox item.

Contributions are welcome :)

Receiver.cs

using System.IO;
using UdtSharp;

namespace p2pconn
{
    static class Receiver
    {
        static internal void Run(UdtSocket connection)
        {
            using (var netStream = new UdtNetworkStream(connection))
            using (var writer = new BinaryWriter(netStream))
            using (var reader = new BinaryReader(netStream))
            {
                string fileName = reader.ReadString();
                long size = reader.ReadInt64();

                byte[] buffer = new byte[4 * 1024 * 1024];

                using (FileStream fileStream = new FileStream(fileName, FileMode.Create))
                {
                    long read = 0;

                    while (read < size)
                    {
                        int toRecv = reader.ReadInt32();

                        ReadFragment(reader, toRecv, buffer);

                        fileStream.Write(buffer, 0, toRecv);

                        read += toRecv;

                        writer.Write(true);
                    }
                }
            }
        }

        static int ReadFragment(BinaryReader reader, int size, byte[] buffer)
        {
            int read = 0;

            while (read < size)
            {
                read += reader.Read(buffer, read, size - read);
            }

            return read;
        }
    }
}

Sender.cs

using System;
using System.IO;
using UdtSharp;

namespace p2pconn
{
    static class Sender
    {
        static internal void Run(UdtSocket connection, string file, bool logVerbose)
        {
            using (var netStream = new UdtNetworkStream(connection))
            using (var writer = new BinaryWriter(netStream))
            using (var reader = new BinaryReader(netStream))
            using (var fileReader = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                long fileSize = new FileInfo(file).Length;

                writer.Write(Path.GetFileName(file));
                writer.Write(fileSize);

                byte[] buffer = new byte[512 * 1024];

                long pos = 0;

                while (pos < fileSize)
                {
                    int toSend = buffer.Length < (fileSize - pos)
                        ? buffer.Length
                        : (int)(fileSize - pos);

                    fileReader.Read(buffer, 0, toSend);

                    int iteration = Environment.TickCount;

                    writer.Write(toSend);
                    connection.Send(buffer, 0, toSend);

                    if (!reader.ReadBoolean())
                    {
                        Console.WriteLine("Error in transmission");
                        return;
                    }

                    pos += toSend;

                    if (logVerbose)
                    {
                        Console.WriteLine();
                        Console.WriteLine("Current: {0} / s",
                            SizeConverter.ConvertToSizeString(toSend / (Environment.TickCount - iteration) * 1000));
                    }
                }
            }
        }
    }
}

SizeConverter.cs

namespace p2pconn
{
    internal enum DataSizeUnit
    {
        Bytes = 1,
        KiloBytes = 1024,
        MegaBytes = 1024 * 1024,
        GigaBytes = 1024 * 1024 * 1024
    };

    internal static class SizeConverter
    {
        internal static string ConvertToSizeString(long size)
        {
            DataSizeUnit totalSizeUnit = SizeConverter.GetSuitableUnit(size);
            return string.Format("{0:#0.##} {1}", SizeConverter.ConvertToSize(
                size, totalSizeUnit), SizeConverter.GetUnitString(totalSizeUnit));
        }

        internal static float ConvertToSize(long size, DataSizeUnit unit)
        {
            return (float)size / (float)unit;
        }

        static string GetUnitString(DataSizeUnit unit)
        {
            switch (unit)
            {
                case DataSizeUnit.Bytes: return "bytes";
                case DataSizeUnit.KiloBytes: return "KB";
                case DataSizeUnit.MegaBytes: return "MB";
                case DataSizeUnit.GigaBytes: return "GB";
            }
            return string.Empty;
        }

        static DataSizeUnit GetSuitableUnit(long size)
        {
            if (size >= 0 && size < (long)DataSizeUnit.KiloBytes)
                return DataSizeUnit.Bytes;
            else if (size >= (long)DataSizeUnit.KiloBytes && size <= (long)DataSizeUnit.MegaBytes)
                return DataSizeUnit.KiloBytes;
            else if (size >= (long)DataSizeUnit.MegaBytes && size <= (long)DataSizeUnit.GigaBytes)
                return DataSizeUnit.MegaBytes;
            else
                return DataSizeUnit.GigaBytes;
        }
    }
}

@leoashish
Copy link

Hey @miroslavpejic85, I would like to contribute to this issue. I have around 6 months of experience in ASP.NET and C#.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

3 participants