-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add FromFile to BinaryData #107231
base: main
Are you sure you want to change the base?
Add FromFile to BinaryData #107231
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -330,6 +330,82 @@ private static async Task<BinaryData> FromStreamAsync(Stream stream, bool async, | |
} | ||
} | ||
|
||
/// <summary> | ||
/// Creates a <see cref="BinaryData"/> instance from the specified file. | ||
/// </summary> | ||
/// <param name="path">The path to the file.</param> | ||
/// <returns>A value representing all of the data from the file.</returns> | ||
public static BinaryData FromFile(string path) | ||
{ | ||
if (path is null) | ||
{ | ||
throw new ArgumentNullException(nameof(path)); | ||
} | ||
|
||
return FromFileAsync(path, async: false).GetAwaiter().GetResult(); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a <see cref="BinaryData"/> instance from the specified file | ||
/// and sets <see cref="MediaType"/> to <see pref="mediaType"/> value. | ||
/// </summary> | ||
/// <param name="path">The path to the file.</param> | ||
/// <param name="mediaType">MIME type of this data, e.g. <see cref="MediaTypeNames.Application.Octet"/>.</param> | ||
/// <returns>A value representing all of the data from the file.</returns> | ||
/// <seealso cref="MediaTypeNames"/> | ||
public static BinaryData FromFile(string path, string? mediaType) | ||
{ | ||
if (path is null) | ||
{ | ||
throw new ArgumentNullException(nameof(path)); | ||
} | ||
|
||
return FromFileAsync(path, async: false, mediaType).GetAwaiter().GetResult(); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a <see cref="BinaryData"/> instance from the specified file. | ||
/// </summary> | ||
/// <param name="path">The path to the file.</param> | ||
/// <param name="cancellationToken">A token that may be used to cancel the operation.</param> | ||
/// <returns>A value representing all of the data from the file.</returns> | ||
public static Task<BinaryData> FromFileAsync(string path, CancellationToken cancellationToken = default) | ||
{ | ||
if (path is null) | ||
{ | ||
throw new ArgumentNullException(nameof(path)); | ||
} | ||
|
||
return FromFileAsync(path, async: true, cancellationToken: cancellationToken); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a <see cref="BinaryData"/> instance from the specified file | ||
/// and sets <see cref="MediaType"/> to <see pref="mediaType"/> value. | ||
/// </summary> | ||
/// <param name="path">The path to the file.</param> | ||
/// <param name="mediaType">MIME type of this data, e.g. <see cref="MediaTypeNames.Application.Octet"/>.</param> | ||
/// <param name="cancellationToken">A token that may be used to cancel the operation.</param> | ||
/// <returns>A value representing all of the data from the file.</returns> | ||
/// <seealso cref="MediaTypeNames"/> | ||
public static Task<BinaryData> FromFileAsync(string path, string? mediaType, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
if (path is null) | ||
{ | ||
throw new ArgumentNullException(nameof(path)); | ||
} | ||
|
||
return FromFileAsync(path, async: true, mediaType, cancellationToken); | ||
} | ||
|
||
private static async Task<BinaryData> FromFileAsync(string path, bool async, | ||
string? mediaType = default, CancellationToken cancellationToken = default) | ||
{ | ||
using FileStream fileStream = File.OpenRead(path); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The FileStream should be opened for asynchronous use when async: true. The way this is written, it'll always use synchronous I/O, which means async operations on it will end up being sync calls queued to the pool. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replaced with the |
||
return await FromStreamAsync(fileStream, async, mediaType, cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a <see cref="BinaryData"/> instance by serializing the provided object using | ||
/// the <see cref="JsonSerializer"/> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to use
File.ReadAllBytes
? Since it has that tries to minimize allocations of the byte array if the file-size is determinable.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question!
The file-size optimization is also supported in the
FromStream
flow.The
ReadAllBytesAsync
method is not available for the net462 and netstandard2.0 TFMs. Can we then fallback to the synchronous implementation for these TFMs?The ReadAllBytes{Async} flow may be more efficient to avoid the intermediate copy buffer of the CopyTo{Async} flow.
Here would be the corresponding code:
Better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. Thanks for looking into it. Personally I don't think the potential benefit outweighs the added complexity, I would keep it as it is then.