cancel
Showing results for 
Search instead for 
Did you mean: 

2004s file download (how to not store files in context?)

Former Member
0 Kudos

Hi,

I want to use FileDownload element in my web dynpro application.

I use the new type resource and my own input source implementation, which generates files on the fly.

Each download call should result in a new file. These files can be very large (some MB).

For obvious reasons I don't want the server to store the byte data in application context (200 users * 2 MB ....)

How can I do this?

If I use resource as context element and set debug points on my input stream, I can see the data is read just on time if the user wants to download.

I create my data in my inputstream and the download starts. So far so good.

On the second click on the download link the download starts without any read operation. Thats the problem.

Possible reasons:

First: the data is read and stored to the context on the first download. this would be bad! context would get very very large. not working for me.

second: the browser or the server caches the data. how can I avoid this?

thx in advance

btw I read a tutorial about up and downloading. this pointed to an additional article called something like "downloading in web dynpro tables". But I can't find it. There the on demand downloading should be explained. any help would be great.

Accepted Solutions (0)

Answers (2)

Answers (2)

Former Member
0 Kudos

Thanks a lot. Maybe this could be a solution.

I'll give it a try. I hope I can avoid the caching (maybe by an additional action handler which sets the resource attribute in context to another value).

Anyway, the solution is far from perfect. In my opinion some redirect without storage should be possible. I really think there should be the possibility to use an inputstream as resource for a file download (without caching or storage).

BeGanz
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hallo Thomas,

I developed a new in-depth tutorial describing this topic: using" on-demand stream in Web Dynpro Tables" or "Downloading resources in Tables on-demand":

<a href="https://www.sdn.sap.comhttp://www.sdn.sap.comhttp://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/b0e10426-77ca-2910-7eb5-d7d8982cb83f">Uploading and Downloading Files in Web Dynpro Tables -</a>.

This new material together with the related sample project will be published on SDN very soon.

Regards, Bertram

Former Member
0 Kudos

Hello,

thanks and sorry for my late response. I was very busy the last time.

Your information is quite helpful but doesn't solve my problem completely. The on demand streaming is quite useful in many situations but not in mine.

The problem apears in the caching as you mention in your tutorial:

"After the first invocation of the getter method, the resource is streamed to the client and keeps cached in the Web Dynpro Binary Cache"

Without this cache the solution would be perfect. But I would like to create a new file for every request.

Does somebody know how to avoid this behaviour? I don't want a cache. I create a new file for every request depending on time and input. I don't want the server to store the file anywhere. Not in context and not in cache. If I wirte a servlet (or a portal component) I can redirect some input stream to the out writer very very easy. And this is exactly my needed behaviour

Former Member
0 Kudos

Hi,

sorry for my late answer, I was busy the last time.

Your tutorial is quite helpful but not the complete solution for my problem. As u mention at the end of your document the calculateMethod is only called once. The data gets stored in a cache.

I don't want this behaviour. My file is created new for every request. In a servlet I just redirect the inputstream to the output stream and everything works fine and easy.

Does somebody know how to avoid the caching?

Thx

Tom

BeGanz
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hallo Thomas,

ok, the "default" on-demand streaming solution caches a Web Resource but does not re-calculate it again afterwards.

I wrote a Wiki Code Tutorial which demonstrates how to download an Excel File from a Web Dynpro table UI element on-demand. In this scenario the resource must also be re-created on every request. The solution is based on re-initializing the context with a new 0-byte resource objects within the calculated context attribute getter method.

See <a href="https://wiki.sdn.sap.com/wiki/display/Snippets/ExportingTableDatainWebDynproJava-SAPNetWeaver04s">Exporting Table Data in Web Dynpro Java - SAP NetWeaver 04s</a>

For you the most important line of code in


//@@begin javadoc:getExcelResourceOnDemStreamCalc(IPrivateExcelExportComp.IExcelElement)
  /**
   *  Declared getter method for attribute ResourceOnDemStreamCalc of node ExcelResource
   *  @param element the element requested for the value
   *  @return the calculated value for attribute ResourceOnDemStreamCalc
   */
  //@@end
  public com.sap.tc.webdynpro.progmodel.api.IWDInputStream getExcelResourceOnDemStreamCalc(IPrivateExcelExportComp.IExcelElement element)
  {
    //@@begin getExcelResourceOnDemStreamCalc(IPrivateExcelExportComp.IExcelElement)
    IWDInputStream excelOnDemandStream = null;
    try {
      excelOnDemandStream =
        WDResourceFactory.createInputStream(toExcel(tableDataNode, tableColumnInfos).getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
      wdComponentAPI.getMessageManager().reportException(e.getLocalizedMessage(), true);
    }

    // Reset context attribute 'Excel.Resource' again by creating a new 0-byte resource object.
    // Otherwise the on-demand Excel stream gets calculated only once as the resource object,
    // cached in the Web Dynpro Binary Cache on server-side, keeps the same.
    initializeOnDemandExcelResource();

    // Return excel on-demand input stream
    return excelOnDemandStream;
    //@@end
  }

is the method <b>call initializedOnDemandExcelResource()</b> re-initializing the context attribute with a new 0-byte resource object.

//@@begin others
  ...
  //======= Private Methods ===========================
  /**
   * Create new on-demand resource instance for excel file. This method must be
   * invoked initially and in the calculated context attribute getter method (calculating)
   * the excel resource input stream. Otherwise the resource is streamed to the client only
   * once but not afterwards so that later updates of the table data are not reflected in the
   * streamed Excel file.
   * URL is stored in context so context in client component can map to it.
   */
  private void initializeOnDemandExcelResource() {
    excel0ByteResource =
      WDResourceFactory.createResource(calcAttrPointer, "Table.xls", WDWebResourceType.XLS);
    excelResourceElement.setResource(excel0ByteResource);
    excelResourceElement.setResourceURL(
      excel0ByteResource.getUrl(WDFileDownloadBehaviour.OPEN_INPLACE.ordinal()));
  }
  ...

Regards, Bertram

Sigiswald
Contributor
0 Kudos

Hi Thomas,

I assume you're already familiar with <a href="http://help.sap.com/saphelp_nw2004s/helpdata/en/42/f6ec5a09321bc7e10000000a11466f/frameset.htm">Loading the InputStream at FileDownload on Demand</a>? The link between the <i>resource</i> attribute and the calculated <i>onDemandStream</i> attribute is defined in <i>wdDoInit</i>. This construction will indeed load the data of the file in the context as soon as someone clicks the link. And it will only load the data once. I suppose if you have a caching problem, e.g. the file should be read again each time the user clicks the download link, this approach won't work.

The very valid question you ask is whether the data of the file is really stored in memory, since that would indeed cause a performance hit when many large files are used. Unfortunately I don't really know... But, still on NW04, where the File<b>Upload</b> UI element only supported the (now deprecated in NW04s) <i>binary</i> <i>data</i> attribute, we had a very similar requirement (many large files). We once tested this where a bunch of users continued uploading files up to 100MB and remarkably, we didn't notice a continuous increase of memory usage. Apparently the data was not stored in memory, at least not permanently (maybe it was temporarily stored until the file was completely uploaded). Later, when having some problems with the virus scanner (which scans uploaded files), we found some more clues (I really don't remember the details) that binary data was not stored in memory, but instead offloaded to some internal "persistent" cache. In reality it could be more complex, e.g. keep files smaller than 10MB in memory and only offload larger files; I really don't know if this is the case.

To summarize: I'm definitely not 100% sure, but I don't think you'll have a problem concerning memory usage. But you should definitely test it for yourself instead of relying on my fuzzy explanation Please let us know your final solution.

BTW, in case the files are known upfront, i.e. not dynamically created, and don't contain any confidential information, you could opt to put them on some web server and use a LinkToURL UI element instead.

Kind regards,

Sigiswald