24
24
import java .util .OptionalLong ;
25
25
26
26
import org .reactivestreams .Publisher ;
27
+ import reactor .core .publisher .Flux ;
27
28
import reactor .core .publisher .Mono ;
28
29
29
30
import org .springframework .core .ResolvableType ;
30
31
import org .springframework .core .codec .ResourceRegionEncoder ;
31
32
import org .springframework .core .io .InputStreamResource ;
32
33
import org .springframework .core .io .Resource ;
34
+ import org .springframework .core .io .buffer .DataBuffer ;
35
+ import org .springframework .core .io .buffer .DataBufferFactory ;
33
36
import org .springframework .core .io .support .ResourceRegion ;
34
37
import org .springframework .http .MediaType ;
35
38
import org .springframework .http .ReactiveHttpOutputMessage ;
36
39
import org .springframework .http .ZeroCopyHttpOutputMessage ;
37
40
38
41
/**
39
- * Implementation of {@link HttpMessageWriter} that can write
40
- * {@link ResourceRegion ResourceRegion}s.
41
- *
42
- * <p>Note that there is no {@link HttpMessageReader} counterpart.
42
+ * Package private helper for {@link ResourceHttpMessageWriter} to assist with
43
+ * writing {@link ResourceRegion ResourceRegion}s.
43
44
*
44
45
* @author Brian Clozel
46
+ * @author Rossen Stoyanchev
45
47
* @since 5.0
46
48
*/
47
- class ResourceRegionHttpMessageWriter extends EncoderHttpMessageWriter < ResourceRegion > {
49
+ class ResourceRegionHttpMessageWriter {
48
50
49
51
public static final String BOUNDARY_STRING_HINT = ResourceRegionHttpMessageWriter .class .getName () + ".boundaryString" ;
50
52
53
+ private static final ResolvableType TYPE = ResolvableType .forClass (ResourceRegion .class );
54
+
55
+
56
+ private final ResourceRegionEncoder encoder ;
57
+
58
+
51
59
public ResourceRegionHttpMessageWriter () {
52
- super ( new ResourceRegionEncoder () );
60
+ this . encoder = new ResourceRegionEncoder ();
53
61
}
54
62
55
63
public ResourceRegionHttpMessageWriter (int bufferSize ) {
56
- super ( new ResourceRegionEncoder (bufferSize ) );
64
+ this . encoder = new ResourceRegionEncoder (bufferSize );
57
65
}
58
66
59
- @ Override
60
- public Mono <Void > write (Publisher <? extends ResourceRegion > inputStream , ResolvableType type ,
61
- MediaType contentType , ReactiveHttpOutputMessage outputMessage , Map <String , Object > hints ) {
67
+
68
+ public Mono <Void > writeRegions (Publisher <? extends ResourceRegion > inputStream , MediaType contentType ,
69
+ ReactiveHttpOutputMessage outputMessage , Map <String , Object > hints ) {
62
70
63
71
if (hints != null && hints .containsKey (BOUNDARY_STRING_HINT )) {
64
72
String boundary = (String ) hints .get (BOUNDARY_STRING_HINT );
65
73
hints .put (ResourceRegionEncoder .BOUNDARY_STRING_HINT , boundary );
66
- outputMessage .getHeaders ()
67
- .setContentType (MediaType .parseMediaType ("multipart/byteranges;boundary=" + boundary ));
68
- return super .write (inputStream , type , contentType , outputMessage , hints );
74
+
75
+ MediaType multipartType = MediaType .parseMediaType ("multipart/byteranges;boundary=" + boundary );
76
+ outputMessage .getHeaders ().setContentType (multipartType );
77
+
78
+ DataBufferFactory bufferFactory = outputMessage .bufferFactory ();
79
+ Flux <DataBuffer > body = this .encoder .encode (inputStream , bufferFactory , TYPE , contentType , hints );
80
+ return outputMessage .writeWith (body );
69
81
}
70
82
else {
71
83
return Mono .from (inputStream )
72
84
.then (region -> {
73
85
writeSingleResourceRegionHeaders (region , contentType , outputMessage );
74
- return writeResourceRegion (region , type , outputMessage );
86
+ return writeResourceRegion (region , outputMessage );
75
87
});
76
88
}
77
89
}
@@ -109,8 +121,8 @@ private OptionalLong contentLength(Resource resource) {
109
121
return OptionalLong .empty ();
110
122
}
111
123
112
- private Mono <Void > writeResourceRegion (ResourceRegion region ,
113
- ResolvableType type , ReactiveHttpOutputMessage outputMessage ) {
124
+ private Mono <Void > writeResourceRegion (ResourceRegion region , ReactiveHttpOutputMessage outputMessage ) {
125
+
114
126
if (outputMessage instanceof ZeroCopyHttpOutputMessage ) {
115
127
Optional <File > file = getFile (region .getResource ());
116
128
if (file .isPresent ()) {
@@ -122,8 +134,13 @@ private Mono<Void> writeResourceRegion(ResourceRegion region,
122
134
}
123
135
124
136
// non-zero copy fallback, using ResourceRegionEncoder
125
- return super .write (Mono .just (region ), type ,
126
- outputMessage .getHeaders ().getContentType (), outputMessage , Collections .emptyMap ());
137
+
138
+ DataBufferFactory bufferFactory = outputMessage .bufferFactory ();
139
+ MediaType contentType = outputMessage .getHeaders ().getContentType ();
140
+ Map <String , Object > hints = Collections .emptyMap ();
141
+
142
+ Flux <DataBuffer > body = this .encoder .encode (Mono .just (region ), bufferFactory , TYPE , contentType , hints );
143
+ return outputMessage .writeWith (body );
127
144
}
128
145
129
146
private static Optional <File > getFile (Resource resource ) {
0 commit comments