選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

LettingTheUserDownloadAFile.asciidoc 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. ---
  2. title: Letting The User Download A File
  3. order: 6
  4. layout: page
  5. ---
  6. [[letting-the-user-download-a-file]]
  7. Letting The User Download A File
  8. --------------------------------
  9. Providing a file for download to the user might be trickier that what it
  10. seems - the file should be downloaded instead of just opened by the
  11. browser, download blockers should be avoided, a unique URL should be
  12. generated and server-side memory should be released when the file is no
  13. longer available for download. All this is taken care of by the new
  14. `FileDownloader` extension that can make almost any component start a
  15. download when clicked.
  16. [source,java]
  17. ....
  18. public class LettingUserDownladFile extends UI {
  19. @Override
  20. protected void init(VaadinRequest request) {
  21. Button downloadButton = new Button("Download image");
  22. StreamResource myResource = createResource();
  23. FileDownloader fileDownloader = new FileDownloader(myResource);
  24. fileDownloader.extend(downloadButton);
  25. setContent(downloadButton);
  26. }
  27. private StreamResource createResource() {
  28. return new StreamResource(new StreamSource() {
  29. @Override
  30. public InputStream getStream() {
  31. String text = "My image";
  32. BufferedImage bi = new BufferedImage(100, 30, BufferedImage.TYPE_3BYTE_BGR);
  33. bi.getGraphics().drawChars(text.toCharArray(), 0, text.length(), 10, 20);
  34. try {
  35. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  36. ImageIO.write(bi, "png", bos);
  37. return new ByteArrayInputStream(bos.toByteArray());
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. return null;
  41. }
  42. }
  43. }, "myImage.png");
  44. }
  45. }
  46. ....
  47. To use `FileDownloader`, you just create an instance of the extension
  48. and use it to extend the component or `MenuItem` that should start the download. You
  49. should also note that `FileDownloader` works best with resources that
  50. are served by Vaadin as it relies on sending some special HTTP headers
  51. along with the file to ensure the browser doesn't try to open the file
  52. even if it's is a file type that the browser knows how to deal with.
  53. [[lazily-determine-the-content-and-the-name-of-the-file-being-server]]
  54. Lazily determine the content and the name of the file being server
  55. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  56. One can lazily determine the content of the file using a
  57. `StreamResource`. Yet the name of the file that is going to be
  58. downloaded has to be known at creation time of the `FileDownloader`. It
  59. seems that a way around this, is in fact missing from Vaadin 7 as of
  60. now.
  61. A possible solution is to subclass `FileDownloader` and set the name right
  62. before the download happens:
  63. [source,java]
  64. ....
  65. /**
  66. * This specializes {@link FileDownloader} in a way, such that both the file name and content can be determined
  67. * on-demand, i.e. when the user has clicked the component.
  68. */
  69. public class OnDemandFileDownloader extends FileDownloader {
  70. /**
  71. * Provide both the {@link StreamSource} and the filename in an on-demand way.
  72. */
  73. public interface OnDemandStreamResource extends StreamSource {
  74. String getFilename ();
  75. }
  76. private static final long serialVersionUID = 1L;
  77. private final OnDemandStreamResource onDemandStreamResource;
  78. public OnDemandFileDownloader (OnDemandStreamResource onDemandStreamResource) {
  79. super(new StreamResource(onDemandStreamResource, ""));
  80. this.onDemandStreamResource = checkNotNull(onDemandStreamResource,
  81. "The given on-demand stream resource may never be null!");
  82. }
  83. @Override
  84. public boolean handleConnectorRequest (VaadinRequest request, VaadinResponse response, String path)
  85. throws IOException {
  86. getResource().setFilename(onDemandStreamResource.getFilename());
  87. return super.handleConnectorRequest(request, response, path);
  88. }
  89. private StreamResource getResource () {
  90. return (StreamResource) this.getResource("dl");
  91. }
  92. }
  93. ....