springrest文档中的文档图像响应

springrest文档中的文档图像响应,spring,spring-restdocs,Spring,Spring Restdocs,我有一个生成随机图像的REST端点。我使用的是SpringREST文档,但是http-Response.adoc文件中的响应都是乱码。模拟MVC和REST文档是否有一种简单的方法将文件存储在某个地方,以便my.adoc文件可以引用它?这不是一个完美但有效的解决方案: class ImageSnippet implements Snippet { private final String filePath; public ImageSnippet(String filePath

我有一个生成随机图像的REST端点。我使用的是SpringREST文档,但是http-Response.adoc文件中的响应都是乱码。模拟MVC和REST文档是否有一种简单的方法将文件存储在某个地方,以便my.adoc文件可以引用它?

这不是一个完美但有效的解决方案:

class ImageSnippet implements Snippet {

    private final String filePath;

    public ImageSnippet(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public void document(Operation operation) throws IOException {
        byte[] picture = operation.getResponse().getContent();

        Path path = Paths.get(filePath);
        Files.deleteIfExists(path);
        Files.createDirectories(path.getParent());
        Files.createFile(path);

        try (FileOutputStream fos = new FileOutputStream(path.toFile())) {
            fos.write(picture);
        }
    }
}
以及在MockMvc测试中的用法(图像文件夹路径很重要):

.adoc
模板中:

 image::barcode.png[]
这是我的
build.gradle
Asciidoctor配置(
imagesdir
很重要):


您所能做的是实现一个保存结果响应的自定义代码段。您可以使用所接收操作的RestDocumentationContext属性来获取输出目录

    mockMvc.perform(get("/example"))
            .andDo(document("some-example", operation -> {
                var context = (RestDocumentationContext) operation.getAttributes().get(RestDocumentationContext.class.getName());
                var path = Paths.get(context.getOutputDirectory().getAbsolutePath(), operation.getName(), "response-file.png");
                Files.createDirectories(path.getParent());
                Files.write(path, operation.getResponse().getContent());
            }));
但是,这将在输出目录中创建一个.png文件,如果在需要嵌入它的源目录中有ASCIDOC,则该文件通常不会真正有用。因此,您可以改为创建一个ascidoc文件,其中包含图像标记的自定义HTML,其源是响应的base64表示形式

    mockMvc.perform(get("/example"))
            .andDo(document("some-example", operation -> {
                var context = (RestDocumentationContext) operation.getAttributes().get(RestDocumentationContext.class.getName());
                var path = Paths.get(context.getOutputDirectory().getAbsolutePath(), operation.getName(), "response-file.adoc");
                var outputStream = new ByteArrayOutputStream();
                outputStream.write("++++\n".getBytes());
                outputStream.write("<img src=\"data:image/png;base64,".getBytes());
                outputStream.write(Base64.getEncoder().encode(operation.getResponse().getContent()));
                outputStream.write("\"/>\n".getBytes());
                outputStream.write("++++\n".getBytes());
                Files.createDirectories(path.getParent());
                Files.write(path, outputStream.toByteArray());
            }));
mockMvc.perform(get(“/example”))
.andDo(文档(“一些示例”,操作->{
var context=(RestDocumentationContext)operation.getAttributes().get(RestDocumentationContext.class.getName());
var path=path.get(context.getOutputDirectory().getAbsolutePath(),operation.getName(),“response file.adoc”);
var outputStream=new ByteArrayOutputStream();
outputStream.write(“+++++\n”.getBytes());
outputStream.write(“\n”.getBytes());
outputStream.write(“+++++\n”.getBytes());
Files.createDirectories(path.getParent());
write(路径,outputStream.toByteArray());
}));

虽然在空间方面有点开销,但是如果你使用这个,您不需要乱引用源代码中的生成文件。

如果您不需要/不想在文档中显示图像,另一种方法是:使用
ContentModifyingOperationPreprocessor
将字节替换为一些字符串,让文档的读者清楚文档中会有一些图像字节答复

    mockMvc.perform(get("/example"))
            .andDo(document("some-example", operation -> {
                var context = (RestDocumentationContext) operation.getAttributes().get(RestDocumentationContext.class.getName());
                var path = Paths.get(context.getOutputDirectory().getAbsolutePath(), operation.getName(), "response-file.adoc");
                var outputStream = new ByteArrayOutputStream();
                outputStream.write("++++\n".getBytes());
                outputStream.write("<img src=\"data:image/png;base64,".getBytes());
                outputStream.write(Base64.getEncoder().encode(operation.getResponse().getContent()));
                outputStream.write("\"/>\n".getBytes());
                outputStream.write("++++\n".getBytes());
                Files.createDirectories(path.getParent());
                Files.write(path, outputStream.toByteArray());
            }));
例如:

        mockMvc.perform(get("/api/users/{id}/avatar", user.getId().asString())
                                .with(createCustomerAuth()))
               .andExpect(status().isOk())
               .andDo(document("get-user-avatar-example",
                               null,
                               Preprocessors.preprocessResponse(new ContentModifyingOperationPreprocessor(new ContentModifier() {
                                   @Override
                                   public byte[] modifyContent(byte[] originalContent, MediaType contentType) {
                                       return "<< IMAGE BODY HERE >>".getBytes(StandardCharsets.UTF_8);
                                   }
                               }))));

您是想让该图像作为HTTP响应代码段的一部分出现在文档中,还是希望在文档中包含该图像以代替HTTP响应代码段?我希望能够将该图像作为HTTP响应代码段的一部分包含进来。抱歉,我不明白您希望它如何工作。你能把你的问题扩展一点,详细描述一下你希望得到的文档是什么样子吗?请注意,HTTP响应片段包含实际的HTTP响应(其标题和正文)。响应主体不是图像,而是可以转换为图像的二进制数据。当我运行生成模拟MVC测试的文档时,我会将.adoc文件作为输出。例如,获取person/1/http-response.adoc。此文件使用源代码语法。我建议图像的输出要么是名为http-response.png的图像字节,要么是名为http-response.adoc并带有image::reference的文件。该引用将指向mockMvc测试生成的映像文件。这是一个不错的选择。不过,我不介意从我的ascidoc中引用构建文件。我还喜欢能够在构建目录中实际查看.png文件,而不必通过ASCIDOC进行渲染。谢谢你的回答!
        mockMvc.perform(get("/api/users/{id}/avatar", user.getId().asString())
                                .with(createCustomerAuth()))
               .andExpect(status().isOk())
               .andDo(document("get-user-avatar-example",
                               null,
                               Preprocessors.preprocessResponse(new ContentModifyingOperationPreprocessor(new ContentModifier() {
                                   @Override
                                   public byte[] modifyContent(byte[] originalContent, MediaType contentType) {
                                       return "<< IMAGE BODY HERE >>".getBytes(StandardCharsets.UTF_8);
                                   }
                               }))));
[source,http,options="nowrap"]
----
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 15
Cache-Control: max-age=3600

<< IMAGE BODY HERE >>
----