另一种选择是使用 XAgent;例如,将beforeRenderResponse 事件设置为:
var fileDb = sessionAsSigner.getDatabase((param.server || ""), param.path);
var fileDocument = fileDb.getDocumentByUNID(param.id);
var attachment = fileDocument.getAttachment(param.filename);
var inputStream = attachment.getInputStream();
var response = facesContext.getExternalContext().getResponse();
/* The following MIME type is generic, should work for all image types;
If you know what type the image will be, set a more specific MIME type */
response.setContentType("application/octet-stream");
var outputStream = response.getOutputStream();
com.acme.xsp.util.StreamUtil.copyStream(inputStream, outputStream);
inputStream.close();
outputStream.close();
attachment.recycle();
fileDocument.recycle();
facesContext.responseComplete();
com.acme.xsp.util.StreamUtil 指的是一种用于将一个流流水线化到另一个流的 Java 便利类:
public class StreamUtil {
public static void copyStream(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
}
因此,不是将您的图像标签直接链接到附件,而是如下所示:
<xp:image url="/download.xsp?server=ACME01&path=images.nsf&id=OU812&filename=photo.jpg" />
这种方法还可以为您提供其他选择:记录访问给定文件的次数、引用 URL(以防您想要实现在 Google 搜索图像时有时会看到的“无热链接”图像替换),或者真的任何你想要的。
作为一个具体的例子,大约十年前,我看到一位同事在内部实现了一个与 Google Analytics 相当的基本功能,甚至可以在不支持 JavaScript 的浏览器上工作,因为他在每个页面上都使用了这种技术来制作公司徽标该站点:他没有直接链接到徽标 JPG,而是链接到一个 PHP 文件,该文件获取 IP、引用者、用户代理等,将所有元数据写入 MySQL 数据库,然后最终将徽标的字节流式传输到浏览器。这显然超出了您想要完成的范围,但我想您可能会觉得有趣的是,这种类型的用例现在在 XPages 中相当简单。