@@ -132,7 +132,7 @@ public partial class PdfReader
132132 /// </summary>
133133 /// <remarks>优先使用 <see cref="Url"/> 未提供 <see cref="Url"/> 时会尝试调用此回调获得流进行渲染</remarks>
134134 [ Parameter ]
135- public Func < Task < Stream > > ? OnGetStreamAsync { get ; set ; }
135+ public Func < Task < Stream ? > > ? OnGetStreamAsync { get ; set ; }
136136
137137 [ Inject , NotNull ]
138138 private IStringLocalizer < PdfReader > ? Localizer { get ; set ; }
@@ -156,6 +156,8 @@ public partial class PdfReader
156156 private bool _enableThumbnails = true ;
157157 private bool _showToolbar = true ;
158158 private PdfReaderFitMode _fitMode ;
159+ private string _lastStreamHash = string . Empty ;
160+ private long _lastStreamLength = 0 ;
159161
160162 /// <summary>
161163 /// <inheritdoc/>
@@ -188,14 +190,16 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
188190 {
189191 _url = Url ;
190192 _currentPage = CurrentPage ;
191- _enableThumbnails = EnableThumbnails ;
193+ _currentRotation = CurrentRotation ;
192194 _showToolbar = ShowToolbar ;
195+ _enableThumbnails = EnableThumbnails ;
193196 _fitMode = FitMode ;
194197 }
195198
196199 if ( _url != Url )
197200 {
198201 _url = Url ;
202+ _lastStreamHash = string . Empty ;
199203 await InvokeVoidAsync ( "setUrl" , Id , _url ) ;
200204 }
201205 if ( _currentPage != CurrentPage )
@@ -229,8 +233,124 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
229233 _fitMode = FitMode ;
230234 await SetFitMode ( _fitMode ) ;
231235 }
236+ if ( string . IsNullOrEmpty ( Url ) )
237+ {
238+ Stream ? stream = null ;
239+ if ( OnGetStreamAsync != null )
240+ {
241+ stream = await OnGetStreamAsync ( ) ;
242+ }
243+
244+ await SetPdfStream ( stream ) ;
245+ }
246+ }
247+
248+ private async Task SetPdfStream ( Stream ? stream )
249+ {
250+ if ( stream == null || stream == Stream . Null )
251+ {
252+ _lastStreamHash = string . Empty ;
253+ _lastStreamLength = 0 ;
254+ await InvokeVoidAsync ( "setData" , Id , null ) ;
255+ return ;
256+ }
257+
258+ byte [ ] pdfBytes = await GetBytes ( stream ) ;
259+
260+ var currentLength = pdfBytes . Length ;
261+ if ( _lastStreamLength != currentLength )
262+ {
263+ _lastStreamLength = currentLength ;
264+ await InvokeVoidAsync ( "setData" , Id , pdfBytes ) ;
265+ return ;
266+ }
267+
268+ #if NET6_0
269+ var currentHash = ComputerHash ( pdfBytes ) ;
270+ #else
271+ var currentHash = await ComputerHash ( stream ) ;
272+ #endif
273+ if ( _lastStreamHash != currentHash )
274+ {
275+ _lastStreamHash = currentHash ;
276+ await InvokeVoidAsync ( "setData" , Id , pdfBytes ) ;
277+ }
278+ }
279+
280+ private async Task < byte [ ] ? > GetPdfStreamDataAsync ( )
281+ {
282+ byte [ ] ? pdfBytes = null ;
283+ if ( OnGetStreamAsync != null )
284+ {
285+ var stream = await OnGetStreamAsync ( ) ;
286+ if ( stream == null || stream == Stream . Null )
287+ {
288+ _lastStreamHash = string . Empty ;
289+ _lastStreamLength = 0 ;
290+ }
291+ else
292+ {
293+ pdfBytes = await GetBytes ( stream ) ;
294+ }
295+ }
296+ return pdfBytes ;
297+ }
298+
299+ private static async Task < byte [ ] > GetBytes ( Stream stream )
300+ {
301+ using var memoryStream = new MemoryStream ( ) ;
302+ await stream . CopyToAsync ( memoryStream ) ;
303+ return memoryStream . ToArray ( ) ;
232304 }
233305
306+ /// <summary>
307+ /// 设置 PDF 流数据方法
308+ /// </summary>
309+ /// <param name="stream"></param>
310+ /// <returns></returns>
311+ public async Task SetPdfStreamAsync ( Stream stream )
312+ {
313+ using var memoryStream = new MemoryStream ( ) ;
314+ await stream . CopyToAsync ( memoryStream ) ;
315+ var pdfBytes = memoryStream . ToArray ( ) ;
316+ _lastStreamLength = pdfBytes . Length ;
317+ #if NET6_0
318+ _lastStreamHash = ComputerHash ( pdfBytes ) ;
319+ #else
320+ _lastStreamHash = await ComputerHash ( stream ) ;
321+ #endif
322+ await InvokeVoidAsync ( "setData" , Id , pdfBytes ) ;
323+ }
324+
325+ /// <summary>
326+ /// 设置 Pdf Base64 数据方法
327+ /// </summary>
328+ /// <param name="base64Data"></param>
329+ /// <returns></returns>
330+ public async Task SetPdfBase64DataAsync ( string base64Data )
331+ {
332+ var pdfBytes = Convert . FromBase64String ( base64Data ) ;
333+ await InvokeVoidAsync ( "setData" , Id , pdfBytes ) ;
334+ }
335+
336+ #if NET6_0
337+ private static string ComputerHash ( byte [ ] data )
338+ {
339+ var hashBytes = System . Security . Cryptography . SHA256 . HashData ( data ) ;
340+ return Convert . ToBase64String ( hashBytes ) ;
341+ }
342+ #else
343+ private static async Task < string > ComputerHash ( Stream stream )
344+ {
345+ if ( stream . CanSeek )
346+ {
347+ stream . Seek ( 0 , SeekOrigin . Begin ) ;
348+ }
349+ var hashBytes = await System . Security . Cryptography . SHA256 . HashDataAsync ( stream ) ;
350+ return Convert . ToBase64String ( hashBytes ) ;
351+ }
352+ #endif
353+
234354 /// <summary>
235355 /// <inheritdoc/>
236356 /// </summary>
@@ -278,19 +398,6 @@ protected override async Task InvokeInitAsync()
278398 /// <returns></returns>
279399 public Task RotateRight ( ) => InvokeVoidAsync ( "rotate" , Id , 90 ) ;
280400
281- private async Task < byte [ ] ? > GetPdfStreamDataAsync ( )
282- {
283- byte [ ] ? pdfBytes = null ;
284- if ( OnGetStreamAsync != null )
285- {
286- using var memoryStream = new MemoryStream ( ) ;
287- var stream = await OnGetStreamAsync ( ) ;
288- await stream . CopyToAsync ( memoryStream ) ;
289- pdfBytes = memoryStream . ToArray ( ) ;
290- }
291- return pdfBytes ;
292- }
293-
294401 /// <summary>
295402 /// 页面开始初始化时回调方法
296403 /// </summary>
0 commit comments