How can I upload a screenshot directly to Imgur?

I have been trying to follow Imgur’s api for uploading images

So far I have been able to get it to properly recognize my Client ID. I know that I am getting through, but I still get a 400 error, which according to Imgur’s documentation means

Status Code: 400
This error indicates that a required parameter is missing or a parameter has a value that is out of bounds or otherwise incorrect. This status code is also returned when image uploads fail due to images that are corrupt or do not meet the format requirements.

This is the code I am using:

IEnumerator AppScreenshot()
	{
		Application.CaptureScreenshot(Application.persistentDataPath + "/screenshot.png");

		WWW www = new WWW(Application.persistentDataPath + "/screenshot.png");
		yield return www;

		WWWForm form = new WWWForm();
		form.AddBinaryData("image", www.bytes);
		Dictionary <string, string> headers = form.headers;
		headers["Authorization"] = "Client-ID <client_id>";
		byte[] rawData = form.data;

		WWW w = new WWW("https://api.imgur.com/3/image", rawData, headers);
		yield return w;
		if (!string.IsNullOrEmpty(w.error))
		{
			print(w.error);
		}
		else
		{
			print(w.responseHeaders["link"]);
		}
	}

The WWW class will not allow me to pass the form directly without converting it to raw bytes first. Is this part of the problem? Why is imgur seemingly unable to accept the image file?

Ok, so after a LOT of google-fu I managed to find a working solution. I had to abandon the use of the WWW class and resort to System.Net instead. Then I ran into a security certificate problem so I found a workaround for that as well. Below is the fully working code for grabbing a screenshot and uploading it to imgur.

IEnumerator AppScreenshotUpload()
	{
		yield return new WaitForEndOfFrame();
		Application.CaptureScreenshot(Application.persistentDataPath + filename);

		//Make sure that the file save properly
		float startTime = Time.time;
		while (false == File.Exists(Application.persistentDataPath + filename))
		{
			if (Time.time - startTime > 5.0f)
			{
				yield break;
			}
			yield return null;
		}

		//Read the saved file back into bytes
		byte[] rawImage = File.ReadAllBytes(Application.persistentDataPath + filename);

		//Before we try uploading it to Imgur we need a Server Certificate Validation Callback
		ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
	
		//Attempt to upload the image
		using (var w = new WebClient())
		{
			string clientID = "put your Client ID here";
			w.Headers.Add("Authorization", "Client-ID " + clientID);
			var values = new NameValueCollection
			{
				{ "image", Convert.ToBase64String(rawImage) },
                { "type", "base64" },
			};

			byte[] response = w.UploadValues("https://api.imgur.com/3/image.xml", values);

			Debug.Log(XDocument.Load(new MemoryStream(response)));
		}
	}

	public bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
	{
		bool isOk = true;
		// If there are errors in the certificate chain, look at each error to determine the cause.
		if (sslPolicyErrors != SslPolicyErrors.None)
		{
			for (int i = 0; i < chain.ChainStatus.Length; i++)
			{
				if (chain.ChainStatus*.Status != X509ChainStatusFlags.RevocationStatusUnknown)*
  •  		{*
    
  •  			chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;*
    
  •  			chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;*
    
  •  			chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);*
    
  •  			chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;*
    
  •  			bool chainIsValid = chain.Build((X509Certificate2)certificate);*
    
  •  			if (!chainIsValid)*
    
  •  			{*
    
  •  				isOk = false;*
    
  •  			}*
    
  •  		}*
    
  •  	}*
    
  •  }*
    
  •  return isOk;*
    
  • }*
    Currently this creates a lot of screenshots in the persistentDataPath location so you might want to just overwrite a single file instead to prevent that. You can get the url of the uploaded image from the MemoryStream(response). In this case you can read it in the Debug.Log after it’s successful. You’ll have to parse it to grab the URL at runtime.

YOUR CODE WORK PERFECT

Also add this :

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Collections.Specialized;
using System.Net;
using System;
using System.Xml.Linq;
using System.IO;

To get link directly replace " Debug.Log " line with this :

XDocument xDoc = XDocument.Load (new MemoryStream (response));

string MyPicUrl;

MyPicUrl = xDoc.Element(“data”).Element(“link”).Value;