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?
Answer by x70x · Mar 07, 2016 at 07:49 PM
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[i].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.
$$anonymous$$aybe it doesn't matter at this point, but FWIW I see several differences here from the WWW version: the URL has an xml extension (likely doesn't matter), explicitly encoding in base64, and also including the type in your submission.
Answer by UnitySeller · Feb 04, 2018 at 03:57 AM
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;