/// <summary> /// Parse the Data inline image. /// </summary> private HtmlImageInfo ReadDataUri(string src) { if (DataUri.TryCreate(src, out DataUri dataUri)) { Size size; knownContentType.TryGetValue(dataUri.Mime, out ImagePartType type); var ipart = mainPart.AddImagePart(type); using (var outputStream = ipart.GetStream(FileMode.Create)) { outputStream.Write(dataUri.Data, 0, dataUri.Data.Length); outputStream.Seek(0L, SeekOrigin.Begin); size = GetImageSize(outputStream); } return(new HtmlImageInfo() { Source = src, ImagePartId = mainPart.GetIdOfPart(ipart), Size = size }); } return(null); }
//____________________________________________________________________ // // Public Functionality /// <summary> /// Download the remote or local image located at the specified url. /// </summary> public HtmlImageInfo Download(string imageUri) { if (prefetchedImages.Contains(imageUri)) { return(prefetchedImages[imageUri]); } if (DataUri.IsWellFormed(imageUri)) // data inline, encoded in base64 { return(ReadDataUri(imageUri)); } return(DownloadRemoteImage(imageUri)); }
/// <summary> /// Parse an instance of the Data URI scheme. /// </summary> /// <param name="uri">The inline Data URI to parse.</param> /// <param name="result">When this method returns, contains a DataUri constructed /// from <paramref name="uri"/>. This parameter is passed uninitialized.</param> /// <returns>A <see cref="Boolean"/> value that is true if the DataUri was /// successfully created; otherwise, false.</returns> public static bool TryCreate(string uri, out DataUri result) { // expected format: data:[<MIME-type>][;charset=<encoding>][;base64],<data> // The encoding is indicated by ;base64. If it's present the data is encoded as base64. Without it the data (as a sequence of octets) // is represented using ASCII encoding for octets inside the range of safe URL characters and using the standard %xx hex encoding // of URLs for octets outside that range. If <MIME-type> is omitted, it defaults to text/plain;charset=US-ASCII. // (As a shorthand, the type can be omitted but the charset parameter supplied.) // Some browsers (Chrome, Opera, Safari, Firefox) accept a non-standard ordering if both ;base64 and ;charset are supplied, // while Internet Explorer requires that the charset's specification must precede the base64 token. // http://en.wikipedia.org/wiki/Data_URI_scheme // We will stick for IE compliance for the moment... Match match = dataUriRegex.Match(uri); result = null; if (!match.Success) { return(false); } byte[] rawData; string mime; Encoding charSet = Encoding.ASCII; // if mime is omitted, set default value as it stands in the norm if (match.Groups["mime"].Length == 0) { mime = "text/plain"; } else { mime = match.Groups["mime"].Value; } if (match.Groups["charset"].Length > 0) { try { charSet = Encoding.GetEncoding(match.Groups["charset"].Value); } catch (ArgumentException) { // charSet was not recognized return(false); } } // is it encoded in base64? if (match.Groups["base64"].Length > 0) { // be careful that the raw data is encoded for url (standard %xx hex encoding) string base64 = HttpUtility.HtmlDecode(match.Groups["data"].Value); try { rawData = Convert.FromBase64String(base64); } catch (FormatException) { // Base64 data is invalid return(false); } } else { // the <data> represents some text (like html snippet) and must be decoded. string raw = HttpUtility.UrlDecode(match.Groups["data"].Value); try { // we convert back to UTF-8 for easier processing later and to have a "referential" encoding rawData = Encoding.Convert(charSet, Encoding.UTF8, charSet.GetBytes(raw)); } catch (ArgumentException) { // UTF-8 Encoded data is invalid return(false); } } result = new DataUri(mime, rawData); return(true); }