Untested performance improvements with uploads, in short the image is directly stored to the upload stream instead of writing a stream to a byte[]. Expecting a small performance improvement, and a lot less memory usage while uploading.

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2125 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2012-10-08 12:58:20 +00:00
parent c983567827
commit abe79e65e9
6 changed files with 230 additions and 182 deletions

View file

@ -30,6 +30,7 @@ using Greenshot.IniFile;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Web;
using Greenshot.Plugin;
namespace GreenshotPlugin.Core {
/// <summary>
@ -58,8 +59,9 @@ namespace GreenshotPlugin.Core {
HttpWebRequest request = (HttpWebRequest)CreateWebRequest(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (request.HaveResponse) {
StreamReader reader = new StreamReader(response.GetResponseStream(), encoding);
return reader.ReadToEnd();
using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding)) {
return reader.ReadToEnd();
}
}
} catch (Exception e) {
@ -241,5 +243,139 @@ namespace GreenshotPlugin.Core {
return sb.ToString();
}
/// <summary>
/// Write Multipart Form Data directly to the HttpWebRequest response stream
/// </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 = String.Format("----------{0:N}", Guid.NewGuid());
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
bool needsCLRF = false;
using (Stream formDataStream = webRequest.GetRequestStream()) {
foreach (var param in postParameters) {
// Thanks to feedback from commenters, 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 IBinaryParameter) {
IBinaryParameter binaryParameter = (IBinaryParameter)param.Value;
binaryParameter.WriteFormDataToStream(boundary, param.Key, formDataStream);
} else {
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
param.Key,
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));
}
}
}
public interface IBinaryParameter {
void WriteFormDataToStream(string boundary, string key, Stream formDataStream);
void WriteToStream(Stream formDataStream);
string ToBase64String();
}
/// <summary>
/// A container to supply files to a Multi-part form data upload
/// </summary>
public class FileParameter : IBinaryParameter {
private byte[] file;
private string fileName;
private string contentType;
private int fileSize;
public FileParameter(byte[] file) : this(file, null) {
}
public FileParameter(byte[] file, string filename) : this(file, filename, null) {
}
public FileParameter(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0) {
}
public FileParameter(byte[] file, string filename, string contenttype, int filesize) {
this.file = file;
this.fileName = filename;
this.contentType = contenttype;
if (filesize == 0) {
this.fileSize = file.Length;
} else {
this.fileSize = filesize;
}
}
public string ToBase64String() {
return System.Convert.ToBase64String(file, 0, fileSize);
}
public void WriteFormDataToStream(string boundary, string key, Stream formDataStream) {
// Add just the first part of this param, since we will write the file data directly to the Stream
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
boundary,
key,
fileName ?? key,
contentType ?? "application/octet-stream");
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
formDataStream.Write(file, 0, fileSize);
}
public void WriteToStream(Stream dataStream) {
// Write the file data directly to the Stream, rather than serializing it to a string.
dataStream.Write(file, 0, fileSize);
}
}
/// <summary>
/// A container to supply images to a Multi-part form data upload
/// </summary>
public class ImageParameter : IBinaryParameter {
private Image image;
private OutputSettings outputSettings;
private string fileName;
public ImageParameter(Image image, OutputSettings outputSettings, string filename) {
this.image = image;
this.outputSettings = outputSettings;
this.fileName = filename;
}
public string ToBase64String() {
using (MemoryStream stream = new MemoryStream()) {
ImageOutput.SaveToStream(image, stream, outputSettings);
return System.Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length);
}
}
public void WriteFormDataToStream(string boundary, string key, Stream formDataStream) {
// Add just the first part of this param, since we will write the file data directly to the Stream
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
boundary,
key,
fileName ?? key,
"image/" + outputSettings.Format.ToString());
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
ImageOutput.SaveToStream(image, formDataStream, outputSettings);
}
public void WriteToStream(Stream dataStream) {
// Write the file data directly to the Stream, rather than serializing it to a string.
ImageOutput.SaveToStream(image, dataStream, outputSettings);
}
}
}