1

I am using C# 4.7.2 and am using a Console and not WinForms. I am trying to get an input of a user's image path then send a post request to a ShareX Image Hoster API.

How can I keep it plain and simple using void? EX:

public static void UploadImg(string ImagePath, string UploadAPI, string UploadKey) { }

ShareX Config:

{
    "Version": "13.2.1",
    "Name": "host",
    "DestinationType": "ImageUploader",
    "RequestMethod": "POST",
    "RequestURL": "https://ADDRESS/upload",
    "Headers": {
        "token": "name_RANDOMSTRING",
        "json": "true"
    },
    "Body": "MultipartFormData",
    "Arguments": {
        "imgfile": null
    },
    "FileFormName": "imgfile",
    "URL": "$json:url$"
}

Capturing traffic with Fiddler I can use these headers:

POST https://IMAGEHOST/api/upload HTTP/1.1
token: SPECIALKEY
json: true
Content-Type: multipart/form-data; boundary=--------------------8d8ee229124e662
User-Agent: ShareX/13.4.0
Host: IMGHOSTER
Content-Length: 7518
Connection: Keep-Alive

----------------------8d8ee229124e662
Content-Disposition: form-data; name="imgfile"; filename="851TO25E8.png"
Content-Type: image/png

Then the rest after these headers is unknown ascii bytes nonsense.

The response is:

{"url":"https://FinalShortenedURL/‌​​​‌‌​‌​‌‌​‌‌‌‌‌‌​​​‌​‌‌‌​​​​​‌​‌​‌‌‌‌‌​​‌‌‌‌​​‌‌‌‌​‌‌‌‌‌​​"}
bananapie
  • 39
  • 1
  • 9

1 Answers1

1

UPDATE - .Net 4.7.2

public static async Task UploadImg(string ImagePath, string UploadAPI, string UploadKey)
{
    using (var client = new System.Net.Http.HttpClient())
    {
        // TODO: implement auth - this example works for bearer tokens:
        // client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", UploadKey);
        // Or you could use simple headers:
        client.DefaultRequestHeaders.Add("token", UploadKey);
        // inject the JSON header... and others if you need them
        client.DefaultRequestHeaders.Add("json", "true");

        var uri = new System.Uri(UploadAPI);

        // Load the file:
        var file = new System.IO.FileInfo(ImagePath);
        if (!file.Exists)
            throw new ArgumentException($"Unable to access file at: {ImagePath}", nameof(ImagePath));

        using (var stream = file.OpenRead())
        {
            var multipartContent = new System.Net.Http.MultipartFormDataContent();
            multipartContent.Add(
                new System.Net.Http.StreamContent(stream),
                "imgfile", // this is the name of FormData field
                file.Name);

            System.Net.Http.HttpRequestMessage request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Post, uri);
            request.Content = multipartContent;
            var response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode(); // this throws an exception on non HTTP success codes
        }
    }
}

The following is the original posted solution for .Net Core to upload using multi-part:

    public static async Task UploadImg(string ImagePath, string UploadAPI, string UploadKey)
    {
        using (var client = new Windows.Web.Http.HttpClient())
        {
            // TODO: implement auth - this example works for bearer tokens:
            client.DefaultRequestHeaders.Authorization = new Windows.Web.Http.Headers.HttpCredentialsHeaderValue("Bearer", UploadKey);
            // Or you could use simple headers:
            client.DefaultRequestHeaders.Add("token", UploadKey);

            // Load the file:
            StorageFile file = await StorageFile.GetFileFromPathAsync(ImagePath);

            var uri = new System.Uri(UploadAPI);

            HttpMultipartFormDataContent multipartContent = new HttpMultipartFormDataContent();

            multipartContent.Add(
                new HttpStreamContent(stream),
                "imgfile", // this is the name of FormData field
                file.Name);

            Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, uri);
            request.Content = multipartContent;
            var response = await client.SendRequestAsync(request);
            response.EnsureSuccessStatusCode(); // this throws an exception on non HTTP success codes
        }
    }

The process is similar in .Net framework, except that you can use System.IO for file operations.

More Information

Having a quick snoop around SO will find many similar questions with similar solutions or pratical advice. This answer is specifically provided to work with OPs ShareX configuration, but if you need further information have a read over these articles:

Chris Schaller
  • 13,704
  • 3
  • 43
  • 81
  • Is Windows.Web.Http.HttpClient() a Library? Or is it a System.Net library HttpClient? If its the first answer can I please get the NuGet package? – bananapie Mar 23 '21 at 21:40
  • I don't know what "HttpCredentialsHeaderValue" is aswell as "StorageFile" is undefined and not in the System.Net library. – bananapie Mar 23 '21 at 22:10
  • @bananapie as I stated in the answer this code is for .Net core, which I know is not what you are asking for, I just don't have an old .Net FX project lying around to try it out in... I'll see what I can do – Chris Schaller Mar 23 '21 at 22:43
  • Do you have a discord I can contact you on and screenshare? – bananapie Mar 23 '21 at 22:45
  • @bananapie I've just updated my post with the code converted to and tested on .Net 4.7.2 – Chris Schaller Mar 23 '21 at 23:13
  • Thanks so much Chris. I'll test it out when I'm back from school – bananapie Mar 24 '21 at 13:30
  • Ok, I modified the code to work. Thanks so much Chris. I just need to figure out how to send the result link to the clipboard of the user. – bananapie Mar 25 '21 at 00:07