mirror of
https://github.com/greenshot/greenshot.git
synced 2025-02-03 02:52:48 -08:00
19fb98ae55
This change makes it possible to use Box, DropBox and Imgur with the default browser, instead of the embedded which causes many issues. Other plugins need to follow.
726 lines
28 KiB
C#
726 lines
28 KiB
C#
/*
|
|
* Greenshot - a free and open source screenshot tool
|
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
|
*
|
|
* For more information see: http://getgreenshot.org/
|
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using log4net;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using GreenshotPlugin.IniFile;
|
|
using GreenshotPlugin.Interfaces;
|
|
using GreenshotPlugin.Interfaces.Plugin;
|
|
|
|
namespace GreenshotPlugin.Core
|
|
{
|
|
/// <summary>
|
|
/// HTTP Method to make sure we have the correct method
|
|
/// </summary>
|
|
public enum HTTPMethod
|
|
{
|
|
GET,
|
|
POST,
|
|
PUT,
|
|
DELETE
|
|
};
|
|
|
|
/// <summary>
|
|
/// Description of NetworkHelper.
|
|
/// </summary>
|
|
public static class NetworkHelper
|
|
{
|
|
private static readonly ILog Log = LogManager.GetLogger(typeof(NetworkHelper));
|
|
private static readonly CoreConfiguration Config = IniConfig.GetIniSection<CoreConfiguration>();
|
|
|
|
static NetworkHelper()
|
|
{
|
|
try
|
|
{
|
|
// Disable certificate checking
|
|
ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Warn("An error has occurred while allowing self-signed certificates:", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Download the uri into a memory stream, without catching exceptions
|
|
/// </summary>
|
|
/// <param name="url">Of an image</param>
|
|
/// <returns>MemoryStream which is already seek-ed to 0</returns>
|
|
public static MemoryStream GetAsMemoryStream(string url)
|
|
{
|
|
var request = CreateWebRequest(url);
|
|
using var response = (HttpWebResponse)request.GetResponse();
|
|
var memoryStream = new MemoryStream();
|
|
using (var responseStream = response.GetResponseStream())
|
|
{
|
|
responseStream?.CopyTo(memoryStream);
|
|
// Make sure it can be used directly
|
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
|
}
|
|
|
|
return memoryStream;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Download the uri to Bitmap
|
|
/// </summary>
|
|
/// <param name="url">Of an image</param>
|
|
/// <returns>Bitmap</returns>
|
|
public static Image DownloadImage(string url)
|
|
{
|
|
var extensions = new StringBuilder();
|
|
foreach (var extension in ImageHelper.StreamConverters.Keys)
|
|
{
|
|
if (string.IsNullOrEmpty(extension))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
extensions.AppendFormat(@"\.{0}|", extension);
|
|
}
|
|
|
|
extensions.Length--;
|
|
|
|
var imageUrlRegex = new Regex($@"(http|https)://.*(?<extension>{extensions})");
|
|
var match = imageUrlRegex.Match(url);
|
|
try
|
|
{
|
|
using var memoryStream = GetAsMemoryStream(url);
|
|
try
|
|
{
|
|
return ImageHelper.FromStream(memoryStream, match.Success ? match.Groups["extension"]?.Value : null);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead.
|
|
string content;
|
|
using (var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true))
|
|
{
|
|
content = streamReader.ReadLine();
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(content))
|
|
{
|
|
throw;
|
|
}
|
|
|
|
match = imageUrlRegex.Match(content);
|
|
if (!match.Success)
|
|
{
|
|
throw;
|
|
}
|
|
|
|
using var memoryStream2 = GetAsMemoryStream(match.Value);
|
|
return ImageHelper.FromStream(memoryStream2, match.Groups["extension"]?.Value);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error("Problem downloading the image from: " + url, e);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper method to create a web request with a lot of default settings
|
|
/// </summary>
|
|
/// <param name="uri">string with uri to connect to</param>
|
|
/// <returns>WebRequest</returns>
|
|
public static HttpWebRequest CreateWebRequest(string uri)
|
|
{
|
|
return CreateWebRequest(new Uri(uri));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper method to create a web request with a lot of default settings
|
|
/// </summary>
|
|
/// <param name="uri">string with uri to connect to</param>
|
|
/// /// <param name="method">Method to use</param>
|
|
/// <returns>WebRequest</returns>
|
|
public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method)
|
|
{
|
|
return CreateWebRequest(new Uri(uri), method);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper method to create a web request with a lot of default settings
|
|
/// </summary>
|
|
/// <param name="uri">Uri with uri to connect to</param>
|
|
/// <param name="method">Method to use</param>
|
|
/// <returns>WebRequest</returns>
|
|
public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method)
|
|
{
|
|
var webRequest = CreateWebRequest(uri);
|
|
webRequest.Method = method.ToString();
|
|
return webRequest;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper method to create a web request, eventually with proxy
|
|
/// </summary>
|
|
/// <param name="uri">Uri with uri to connect to</param>
|
|
/// <returns>WebRequest</returns>
|
|
public static HttpWebRequest CreateWebRequest(Uri uri)
|
|
{
|
|
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
|
|
webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null;
|
|
// Make sure the default credentials are available
|
|
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
|
|
|
// Allow redirect, this is usually needed so that we don't get a problem when a service moves
|
|
webRequest.AllowAutoRedirect = true;
|
|
// Set default timeouts
|
|
webRequest.Timeout = Config.WebRequestTimeout * 1000;
|
|
webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout * 1000;
|
|
return webRequest;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a IWebProxy Object which can be used to access the Internet
|
|
/// This method will check the configuration if the proxy is allowed to be used.
|
|
/// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins
|
|
/// </summary>
|
|
/// <param name="uri"></param>
|
|
/// <returns>IWebProxy filled with all the proxy details or null if none is set/wanted</returns>
|
|
public static IWebProxy CreateProxy(Uri uri)
|
|
{
|
|
IWebProxy proxyToUse = null;
|
|
if (!Config.UseProxy)
|
|
{
|
|
return proxyToUse;
|
|
}
|
|
|
|
proxyToUse = WebRequest.DefaultWebProxy;
|
|
if (proxyToUse != null)
|
|
{
|
|
proxyToUse.Credentials = CredentialCache.DefaultCredentials;
|
|
if (!Log.IsDebugEnabled)
|
|
{
|
|
return proxyToUse;
|
|
}
|
|
|
|
// check the proxy for the Uri
|
|
if (!proxyToUse.IsBypassed(uri))
|
|
{
|
|
var proxyUri = proxyToUse.GetProxy(uri);
|
|
if (proxyUri != null)
|
|
{
|
|
Log.Debug("Using proxy: " + proxyUri + " for " + uri);
|
|
}
|
|
else
|
|
{
|
|
Log.Debug("No proxy found!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log.Debug("Proxy bypass for: " + uri);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log.Debug("No proxy found!");
|
|
}
|
|
|
|
return proxyToUse;
|
|
}
|
|
|
|
/// <summary>
|
|
/// UrlEncodes a string without the requirement for System.Web
|
|
/// </summary>
|
|
/// <param name="text"></param>
|
|
/// <returns></returns>
|
|
// [Obsolete("Use System.Uri.EscapeDataString instead")]
|
|
public static string UrlEncode(string text)
|
|
{
|
|
if (!string.IsNullOrEmpty(text))
|
|
{
|
|
// System.Uri provides reliable parsing, but doesn't encode spaces.
|
|
return Uri.EscapeDataString(text).Replace("%20", "+");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// A wrapper around the EscapeDataString, as the limit is 32766 characters
|
|
/// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx
|
|
/// </summary>
|
|
/// <param name="text"></param>
|
|
/// <returns>escaped data string</returns>
|
|
public static string EscapeDataString(string text)
|
|
{
|
|
if (!string.IsNullOrEmpty(text))
|
|
{
|
|
var result = new StringBuilder();
|
|
int currentLocation = 0;
|
|
while (currentLocation < text.Length)
|
|
{
|
|
string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation));
|
|
result.Append(Uri.EscapeDataString(process));
|
|
currentLocation += 16384;
|
|
}
|
|
|
|
return result.ToString();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// UrlDecodes a string without requiring System.Web
|
|
/// </summary>
|
|
/// <param name="text">String to decode.</param>
|
|
/// <returns>decoded string</returns>
|
|
public static string UrlDecode(string text)
|
|
{
|
|
// pre-process for + sign space formatting since System.Uri doesn't handle it
|
|
// plus literals are encoded as %2b normally so this should be safe
|
|
text = text.Replace("+", " ");
|
|
return Uri.UnescapeDataString(text);
|
|
}
|
|
|
|
/// <summary>
|
|
/// ParseQueryString without the requirement for System.Web
|
|
/// </summary>
|
|
/// <param name="queryString"></param>
|
|
/// <returns>IDictionary string, string</returns>
|
|
public static IDictionary<string, string> ParseQueryString(string queryString)
|
|
{
|
|
IDictionary<string, string> parameters = new SortedDictionary<string, string>();
|
|
// remove anything other than query string from uri
|
|
if (queryString.Contains("?"))
|
|
{
|
|
queryString = queryString.Substring(queryString.IndexOf('?') + 1);
|
|
}
|
|
|
|
foreach (string vp in Regex.Split(queryString, "&"))
|
|
{
|
|
if (string.IsNullOrEmpty(vp))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string[] singlePair = Regex.Split(vp, "=");
|
|
if (parameters.ContainsKey(singlePair[0]))
|
|
{
|
|
parameters.Remove(singlePair[0]);
|
|
}
|
|
|
|
parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty);
|
|
}
|
|
|
|
return parameters;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate the query parameters
|
|
/// </summary>
|
|
/// <param name="queryParameters">the list of query parameters</param>
|
|
/// <returns>a string with the query parameters</returns>
|
|
public static string GenerateQueryParameters(IDictionary<string, object> queryParameters)
|
|
{
|
|
if (queryParameters == null || queryParameters.Count == 0)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
queryParameters = new SortedDictionary<string, object>(queryParameters);
|
|
|
|
var sb = new StringBuilder();
|
|
foreach (string key in queryParameters.Keys)
|
|
{
|
|
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode($"{queryParameters[key]}"));
|
|
}
|
|
|
|
sb.Remove(sb.Length - 1, 1);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write Multipart Form Data directly to the HttpWebRequest
|
|
/// </summary>
|
|
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
|
|
/// <param name="postParameters">Parameters to include in the multipart form data</param>
|
|
public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary<string, object> postParameters)
|
|
{
|
|
string boundary = $"----------{Guid.NewGuid():N}";
|
|
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
|
|
using Stream formDataStream = webRequest.GetRequestStream();
|
|
WriteMultipartFormData(formDataStream, boundary, postParameters);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write Multipart Form Data to a Stream, content-type should be set before this!
|
|
/// </summary>
|
|
/// <param name="formDataStream">Stream to write the multipart form data to</param>
|
|
/// <param name="boundary">String boundary for the multipart/form-data</param>
|
|
/// <param name="postParameters">Parameters to include in the multipart form data</param>
|
|
public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary<string, object> postParameters)
|
|
{
|
|
bool needsClrf = false;
|
|
foreach (var param in postParameters)
|
|
{
|
|
// Add a CRLF to allow multiple parameters to be added.
|
|
// Skip it on the first parameter, add it to subsequent parameters.
|
|
if (needsClrf)
|
|
{
|
|
formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n"));
|
|
}
|
|
|
|
needsClrf = true;
|
|
|
|
if (param.Value is IBinaryContainer binaryContainer)
|
|
{
|
|
binaryContainer.WriteFormDataToStream(boundary, param.Key, formDataStream);
|
|
}
|
|
else
|
|
{
|
|
string postData = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{param.Key}\"\r\n\r\n{param.Value}";
|
|
formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData));
|
|
}
|
|
}
|
|
|
|
// Add the end of the request. Start with a newline
|
|
string footer = "\r\n--" + boundary + "--\r\n";
|
|
formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Post content HttpWebRequest
|
|
/// </summary>
|
|
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
|
|
/// <param name="headers">IDictionary with the headers</param>
|
|
/// <param name="binaryContainer">IBinaryContainer</param>
|
|
public static void Post(HttpWebRequest webRequest, IDictionary<string, object> headers, IBinaryContainer binaryContainer = null)
|
|
{
|
|
foreach (var header in headers)
|
|
{
|
|
switch (header.Key)
|
|
{
|
|
case "Content-Type":
|
|
webRequest.ContentType = header.Value as string;
|
|
break;
|
|
case "Accept":
|
|
webRequest.Accept = header.Value as string;
|
|
break;
|
|
default:
|
|
webRequest.Headers.Add(header.Key, Convert.ToString(header.Value));
|
|
break;
|
|
}
|
|
}
|
|
if (!headers.ContainsKey("Content-Type"))
|
|
{
|
|
webRequest.ContentType = "application/octet-stream";
|
|
}
|
|
|
|
if (binaryContainer != null)
|
|
{
|
|
using var requestStream = webRequest.GetRequestStream();
|
|
binaryContainer.WriteToStream(requestStream);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Post content HttpWebRequest
|
|
/// </summary>
|
|
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
|
|
/// <param name="headers">IDictionary with the headers</param>
|
|
/// <param name="jsonString">string</param>
|
|
public static void Post(HttpWebRequest webRequest, IDictionary<string, object> headers, string jsonString)
|
|
{
|
|
if (headers != null)
|
|
{
|
|
foreach (var header in headers)
|
|
{
|
|
switch (header.Key)
|
|
{
|
|
case "Content-Type":
|
|
webRequest.ContentType = header.Value as string;
|
|
break;
|
|
case "Accept":
|
|
webRequest.Accept = header.Value as string;
|
|
break;
|
|
default:
|
|
webRequest.Headers.Add(header.Key, Convert.ToString(header.Value));
|
|
break;
|
|
}
|
|
}
|
|
if (!headers.ContainsKey("Content-Type"))
|
|
{
|
|
webRequest.ContentType = "application/json";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
webRequest.ContentType = "application/json";
|
|
}
|
|
|
|
if (jsonString != null)
|
|
{
|
|
using var requestStream = webRequest.GetRequestStream();
|
|
using var streamWriter = new StreamWriter(requestStream);
|
|
streamWriter.Write(jsonString);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Post the parameters "x-www-form-urlencoded"
|
|
/// </summary>
|
|
/// <param name="webRequest"></param>
|
|
/// <param name="parameters"></param>
|
|
public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary<string, object> parameters)
|
|
{
|
|
webRequest.ContentType = "application/x-www-form-urlencoded";
|
|
string urlEncoded = GenerateQueryParameters(parameters);
|
|
|
|
byte[] data = Encoding.UTF8.GetBytes(urlEncoded);
|
|
using var requestStream = webRequest.GetRequestStream();
|
|
requestStream.Write(data, 0, data.Length);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Log the headers of the WebResponse, if IsDebugEnabled
|
|
/// </summary>
|
|
/// <param name="response">WebResponse</param>
|
|
private static void DebugHeaders(WebResponse response)
|
|
{
|
|
if (!Log.IsDebugEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log.DebugFormat("Debug information on the response from {0} :", response.ResponseUri);
|
|
foreach (string key in response.Headers.AllKeys)
|
|
{
|
|
Log.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Process the web response.
|
|
/// </summary>
|
|
/// <param name="webRequest">The request object.</param>
|
|
/// <returns>The response data.</returns>
|
|
/// TODO: This method should handle the StatusCode better!
|
|
public static string GetResponseAsString(HttpWebRequest webRequest)
|
|
{
|
|
return GetResponseAsString(webRequest, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read the response as string
|
|
/// </summary>
|
|
/// <param name="response"></param>
|
|
/// <returns>string or null</returns>
|
|
private static string GetResponseAsString(HttpWebResponse response)
|
|
{
|
|
string responseData = null;
|
|
if (response == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
using (response)
|
|
{
|
|
Stream responseStream = response.GetResponseStream();
|
|
if (responseStream != null)
|
|
{
|
|
using StreamReader reader = new StreamReader(responseStream, true);
|
|
responseData = reader.ReadToEnd();
|
|
}
|
|
}
|
|
|
|
return responseData;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="webRequest"></param>
|
|
/// <param name="alsoReturnContentOnError"></param>
|
|
/// <returns></returns>
|
|
public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError)
|
|
{
|
|
string responseData = null;
|
|
HttpWebResponse response = null;
|
|
bool isHttpError = false;
|
|
try
|
|
{
|
|
response = (HttpWebResponse)webRequest.GetResponse();
|
|
Log.InfoFormat("Response status: {0}", response.StatusCode);
|
|
isHttpError = (int)response.StatusCode >= 300;
|
|
if (isHttpError)
|
|
{
|
|
Log.ErrorFormat("HTTP error {0}", response.StatusCode);
|
|
}
|
|
|
|
DebugHeaders(response);
|
|
responseData = GetResponseAsString(response);
|
|
if (isHttpError)
|
|
{
|
|
Log.ErrorFormat("HTTP response {0}", responseData);
|
|
}
|
|
}
|
|
catch (WebException e)
|
|
{
|
|
response = (HttpWebResponse)e.Response;
|
|
HttpStatusCode statusCode = HttpStatusCode.Unused;
|
|
if (response != null)
|
|
{
|
|
statusCode = response.StatusCode;
|
|
Log.ErrorFormat("HTTP error {0}", statusCode);
|
|
string errorContent = GetResponseAsString(response);
|
|
if (alsoReturnContentOnError)
|
|
{
|
|
return errorContent;
|
|
}
|
|
|
|
Log.ErrorFormat("Content: {0}", errorContent);
|
|
}
|
|
|
|
Log.Error("WebException: ", e);
|
|
if (statusCode == HttpStatusCode.Unauthorized)
|
|
{
|
|
throw new UnauthorizedAccessException(e.Message);
|
|
}
|
|
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
if (response != null)
|
|
{
|
|
if (isHttpError)
|
|
{
|
|
Log.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData);
|
|
}
|
|
|
|
response.Close();
|
|
}
|
|
}
|
|
|
|
return responseData;
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// This interface can be used to pass binary information around, like byte[] or Image
|
|
/// </summary>
|
|
public interface IBinaryContainer
|
|
{
|
|
void WriteFormDataToStream(string boundary, string name, Stream formDataStream);
|
|
void WriteToStream(Stream formDataStream);
|
|
string ToBase64String(Base64FormattingOptions formattingOptions);
|
|
byte[] ToByteArray();
|
|
void Upload(HttpWebRequest webRequest);
|
|
|
|
string ContentType { get; }
|
|
string Filename { get; set; }
|
|
}
|
|
|
|
/// A container to supply surfaces to a Multi-part form data upload
|
|
/// </summary>
|
|
public class SurfaceContainer : IBinaryContainer
|
|
{
|
|
private readonly ISurface _surface;
|
|
private readonly SurfaceOutputSettings _outputSettings;
|
|
|
|
public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename)
|
|
{
|
|
_surface = surface;
|
|
_outputSettings = outputSettings;
|
|
Filename = filename;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a Base64String from the Surface by saving it to a memory stream and converting it.
|
|
/// Should be avoided if possible, as this uses a lot of memory.
|
|
/// </summary>
|
|
/// <returns>string</returns>
|
|
public string ToBase64String(Base64FormattingOptions formattingOptions)
|
|
{
|
|
using MemoryStream stream = new MemoryStream();
|
|
ImageOutput.SaveToStream(_surface, stream, _outputSettings);
|
|
return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a byte[] from the image by saving it to a memory stream.
|
|
/// Should be avoided if possible, as this uses a lot of memory.
|
|
/// </summary>
|
|
/// <returns>byte[]</returns>
|
|
public byte[] ToByteArray()
|
|
{
|
|
using MemoryStream stream = new MemoryStream();
|
|
ImageOutput.SaveToStream(_surface, stream, _outputSettings);
|
|
return stream.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write Multipart Form Data directly to the HttpWebRequest response stream
|
|
/// </summary>
|
|
/// <param name="boundary">Multipart separator</param>
|
|
/// <param name="name">Name of the thing</param>
|
|
/// <param name="formDataStream">Stream to write to</param>
|
|
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream)
|
|
{
|
|
// Add just the first part of this param, since we will write the file data directly to the Stream
|
|
string header = $"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"; filename=\"{Filename ?? name}\";\r\nContent-Type: {ContentType}\r\n\r\n";
|
|
|
|
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
|
ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A plain "write data to stream"
|
|
/// </summary>
|
|
/// <param name="dataStream"></param>
|
|
public void WriteToStream(Stream dataStream)
|
|
{
|
|
// Write the file data directly to the Stream, rather than serializing it to a string.
|
|
ImageOutput.SaveToStream(_surface, dataStream, _outputSettings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upload the Surface as image to the webrequest
|
|
/// </summary>
|
|
/// <param name="webRequest"></param>
|
|
public void Upload(HttpWebRequest webRequest)
|
|
{
|
|
webRequest.ContentType = ContentType;
|
|
using var requestStream = webRequest.GetRequestStream();
|
|
WriteToStream(requestStream);
|
|
}
|
|
|
|
public string ContentType => "image/" + _outputSettings.Format;
|
|
public string Filename { get; set; }
|
|
}
|
|
} |