camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > File
Date Sat, 18 Jul 2009 06:08:00 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1519/1/1/_/styles/combined.css?spaceKey=CAMEL&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><a href="http://cwiki.apache.org/confluence/display/CAMEL/File">File</a></h2>
     <h4>Page <b>edited</b> by             <a href="http://cwiki.apache.org/confluence/display/~davsclaus">Claus
Ibsen</a>
    </h4>
     
          <br/>
     <div class="notificationGreySide">
         <h2><a name="File-FileComponentCamel1.xonly"></a>File Component
- <b>Camel 1.x only</b></h2>

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Using Camel
2.x</b><br /><p>This page is only for Camel 1.x. If you are using Camel
2.0 or newer see this <a href="/confluence/display/CAMEL/File2" title="File2">link</a>.</p></td></tr></table></div>


<p>The File component provides access to file systems; allowing files to be processed
by any other Camel <a href="/confluence/display/CAMEL/Components" title="Components">Components</a>
or messages from other components can be saved to disk.</p>

<h3><a name="File-URIformat"></a>URI format</h3>

<style type="text/css">
@import url(/confluence/download/resources/confluence.ext.code:code/shStyles.css);
</style>
<!--[if IE]>
<style type="text/css">
    .code textarea, .code input { padding: 0 !important; }
</style>
<![endif]-->
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shCore.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushCSharp.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushPhp.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushJScript.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushVb.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushSql.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushXml.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushShell.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushDelphi.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushPython.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushJava.js"></script>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">file:fileOrDirectoryName[?options]</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>or</p>

<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">file://fileOrDirectoryName[?options]</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>Where <b>fileOrDirectoryName</b> represents the underlying file name.
Camel will determine if <b>fileOrDirectoryName</b> is a file or directory.</p>

<p>You can append query options to the URI in the following format, <tt>?option=value&amp;option=value&amp;...</tt></p>

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Important
Information</b><br /><p>See the section "Common gotchas with folder and
filenames" below.</p></td></tr></table></div>

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Timestamp</b><br
/><p>In Camel 1.5 or older the file consumer uses an internal timestamp for last
polling. This timestamp is used to match for new or changed files: if file modified timestamp
&gt; last poll timestamp =&gt; file can be consumed. Beware that its not persistent
in any way so restarting Camel will restart the lastpolltime variable and you can potentially
consume the same file again.</p>

<p>You can disable this algorithm with the new option <b>consumer.timestamp=false</b>
or setting the <b>consumer.alwaysConsume=true</b>. Camel keeps track of consumed
files which leads to a memory leak for large number of files in Camel 1.5.0 and older. This
was replaced with a LRU cache in Camel 1.6.0.</p>

<p><b>Notice:</b> This algorithm has been marked for <tt>@deprecation</tt>
and has been removed in Camel 2.0. We <b>strongly</b> encourage you to use a different
strategy for matching new files: such as deleting or moving the file after processing, then
new files is always if there exists a file in the directory to poll.</p></td></tr></table></div>

<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif" width="16"
height="16" align="absmiddle" alt="" border="0"></td><td><b>Cannot move/delete
file after processing on Windows</b><br /><p>There is a potential issue
on Windows platform with Camel 1.5.x. That it cannot move or delete the file after processing.
You should get an exception thrown.<br/>
The workaround is to convert the body to a <tt>String</tt> after consuming using
<tt>convertBodyTo</tt>: eg <tt>from("file://inbox").convertBodyTo(String.class).to("file://outbox");</tt>.<br/>
There should be a fix in Camel 1.6.0 to remedy this, but we would like to get feedback on
this issue. So if you are on Windows please give it a go.</p></td></tr></table></div>


<h3><a name="File-URIOptions"></a>URI Options</h3>
<div class="confluenceTableSmall"><table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Name </th>
<th class='confluenceTh'> Default Value </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.initialDelay</tt> </td>
<td class='confluenceTd'> <tt>1000</tt> </td>
<td class='confluenceTd'> Camel 1.4: milliseconds before polling the file/directory
starts</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.delay</tt> </td>
<td class='confluenceTd'> <tt>500</tt> </td>
<td class='confluenceTd'>Camel 1.4: milliseconds before the next poll of the file/directory</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.useFixedDelay</tt> </td>
<td class='confluenceTd'> <tt>false</tt> </td>
<td class='confluenceTd'> Camel 1.4:  <tt>true</tt> to use fixed delay between
pools, otherwise fixed rate is used. See <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ScheduledExecutorService.html"
rel="nofollow">ScheduledExecutorService</a> in JDK for details.</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.exclusiveReadLock</tt> </td>
<td class='confluenceTd'> <tt>true</tt> </td>
<td class='confluenceTd'> Camel 1.5: Used by <tt>FileConsumer</tt>. If set
to <tt>true</tt> Camel will only poll the files if it has exclusive read lock
to the file (= the file is not in progress of being written). Camel will wait until the file
lock is granted. Setting to <tt>false</tt> Camel will poll the file even if its
in progress of being written (= this is the behavior of Camel 1.4). </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.recursive</tt> </td>
<td class='confluenceTd'> <tt>true</tt>/<tt>false</tt> </td>
<td class='confluenceTd'> If a directory, will look for changes in files in all the
sub directories. <b>Notice:</b> Default value in Camel 1.4 or older is <tt>true</tt>.
In Camel 1.5 the default value is changed to <tt>false</tt>. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.regexPattern</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> Will only fire a an exchange for a file that matches the regex
pattern. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.alwaysConsume</tt> </td>
<td class='confluenceTd'> <tt>false</tt> </td>
<td class='confluenceTd'> Camel 1.5: <b>@deprecated</b>. Is used to force
consuming the file even if it hasn't changed since last time it was consumed. Is useful if
you, for instance, move files back into a folder and the file keeps the original timestamp.
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.timestamp</tt> </td>
<td class='confluenceTd'> <tt>true</tt> </td>
<td class='confluenceTd'> Camel 1.5: <b>@deprecated</b>. This option is
introduced to have similar name as the same option in <a href="/confluence/display/CAMEL/FTP"
title="FTP">FTP</a> component. Setting this option will internally in Camel set the
<b>consumer.alwaysConsume</b> option to the <tt>! value</tt>. So if
this option is <tt>true</tt>, <tt>alwaysConsume</tt> is <tt>false</tt>
and vice versa. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>consumer.generateEmptyExchangeWhenIdle</tt>
</td>
<td class='confluenceTd'> <tt>false</tt> </td>
<td class='confluenceTd'> <b>@deprecated</b>. Option only for the <tt>FileConsumer</tt>.
If this option is <tt>true</tt> and there was no files to process we simulate
processing a single empty file, so an exchange is fired. <b>Note:</b> In this
situation the <tt>File</tt> attribute in <tt>FileExchange</tt> is
<tt>null</tt>. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>lock</tt> </td>
<td class='confluenceTd'> <tt>true</tt> </td>
<td class='confluenceTd'> If <tt>true</tt>, will lock the file for the duration
of the processing. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>delete</tt> </td>
<td class='confluenceTd'> <tt>false</tt> </td>
<td class='confluenceTd'> If <tt>true</tt>, the file will be deleted when
it is processed (the default is to move it, see below) </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>noop</tt> </td>
<td class='confluenceTd'> <tt>false</tt> </td>
<td class='confluenceTd'> If <tt>true</tt>, the file is not moved or deleted
in any way (see below). This option is good for read only data, or for <a href="/confluence/display/CAMEL/ETL"
title="ETL">ETL</a> type requirements. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>moveNamePrefix</tt> </td>
<td class='confluenceTd'> <tt>.camel/</tt> </td>
<td class='confluenceTd'> The prefix string prepended to the filename when moving it.
For example, to move processed files into the <tt>done</tt> directory, set this
value to <tt>done/</tt> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>moveNamePostfix</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> The postfix string appended to the filename when moving it.
For example, to rename processed files from <tt>foo</tt> to <tt>foo.old</tt>
set this value to <tt>.old</tt> </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>append</tt> </td>
<td class='confluenceTd'> <tt>true</tt> </td>
<td class='confluenceTd'> When writing, do we append to the end of the file, or replace
it? </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>autoCreate</tt> </td>
<td class='confluenceTd'> <tt>true</tt> </td>
<td class='confluenceTd'> If set to <tt>true</tt>, Camel will create any
missing directories in the file's pathname. Uses <tt>File&#35;mkdirs()</tt>
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>bufferSize</tt> </td>
<td class='confluenceTd'> <tt>128kb</tt> </td>
<td class='confluenceTd'> Write buffer sized in bytes. Camel uses a default of 128 *
1024 bytes. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>ignoreFileNameHeader</tt> </td>
<td class='confluenceTd'> <tt>false</tt> </td>
<td class='confluenceTd'> <b>@deprecated</b>. If this flag is enabled, then
producers will ignore the <tt>org.apache.camel.file.name</tt> header and generate
a new dynamic filename. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>excludedNamePrefixes</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> <b>@deprecated</b>. Is used to exclude files if
filename is starting with any of the given prefixes. The parameter is a <tt>String[]</tt>
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>excludedNamePostfixes</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> <b>@deprecated</b>. Is used to exclude files if
filename is ending with any of the given prefixes. The parameter is a <tt>String[]</tt>
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>excludedNamePrefix</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> Camel 1.5: Excludes files whose filename starts with the given
prefix. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>excludedNamePostfix</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> Camel 1.5: Excludes files whose filename ends with the given
postfix. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>expression</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> Camel 1.5: Use expression to dynamically set the filename.
This allows you very easily to set dynamic pattern style filenames. If an expression is set
it take precedes over the <tt>org.apache.camel.file.name</tt> header. (Note: The
header can itself also be an expression). The expression options supports both <tt>String</tt>
and <tt>Expression</tt> types. If the expression is a <tt>String</tt>
type, then it is <b>always</b> evaluated using the <a href="/confluence/display/CAMEL/File+Language"
title="File Language">File Language</a>. If the expression is an <tt>Expression</tt>
type, then the specified <tt>Expression</tt> type is used - this allows you, for
instance, to use <a href="/confluence/display/CAMEL/OGNL" title="OGNL">OGNL</a>
expressions. </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>preMoveNamePrefix</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> Camel 1.5.1/2.0: The prefix string prepended to the filename
when moving it <b>before</b> processing. For example, to move in-progress files
to the <tt>inprogress</tt> directory, set this option to <tt>inprogress/</tt>
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>preMoveNamePostfix</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> Camel 1.5.1/2.0: The postfix string appended to the filename
when moving it <b>before</b> processing. For example, to rename in-progress files
from <tt>foo</tt> to <tt>foo.inprogress</tt> set this option to <tt>.inprogress</tt>
</td>
</tr>
<tr>
<td class='confluenceTd'> <tt>preMoveExpression</tt> </td>
<td class='confluenceTd'> <tt>null</tt> </td>
<td class='confluenceTd'> Camel 1.5.1/2.0: Use an expression to dynamically set the
filename when moving it <b>before</b> processing. For example to move in-progress
files into the <tt>order</tt> directory and use <tt>.bak</tt> as the
extension, set this value to <tt>order/${<a href="file:name.noext" rel="nofollow">file:name.noext</a>}.bat</tt>
</td>
</tr>
</tbody></table></div>

<h3><a name="File-Defaultbehaviorforfileconsumer"></a>Default behavior for
file consumer</h3>
<ul>
	<li>By default, the file is locked for the duration of the processing.</li>
	<li>After the route has completed, files are moved into the <tt>.camel</tt>
subdirectory, so that they appear to be deleted.</li>
	<li>The File Consumer will always skip any file whose name starts with a dot, such
as <tt>.</tt>, <tt>.camel</tt>, <tt>.m2</tt> or <tt>.groovy</tt>.</li>
	<li>Only files (not directories) are matched for valid filename, if options such as:
<tt>consumer.regexPattern</tt>, <tt>excludeNamePrefix</tt>, <tt>excludeNamePostfix</tt>
are used. <b>Notice:</b> this only works properly in Camel 1.5.0, due to issue
<a href="http://issues.apache.org/activemq/browse/CAMEL-920" rel="nofollow">CAMEL-920</a>.</li>
</ul>


<h4><a name="File-DefaultBehaviorChangedinCamel1.5.0"></a>Default Behavior
Changed in Camel 1.5.0</h4>
<p>In Camel 1.5, the file consumer will avoid polling files that are currently in the
progress of being written (see option <b>consumer.exclusiveReadLock</b>). However,
this requires Camel to be able to rename the file for its testing. If the Camel user has not
got the relevant rights on the file system, you can set this option to <tt>false</tt>
to revert to the default behavior of Camel 1.4 or older.</p>

<p>The recursive option has changed its default value from <tt>true</tt>
to <tt>false</tt> in Camel 1.5.0.</p>

<h3><a name="File-MoveandDeleteoperations"></a>Move and Delete operations</h3>
<p>Any move or delete operation is executed after (post command) the routing has completed.
So, during processing of the <tt>Exchange</tt> the file is still located in the
<tt>inbox</tt> folder. <br/>
Let's illustrate this with an example:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("file://inbox?m
oveNamePrefix=done/").to("bean:handleOrder");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>

<p>When a file is dropped in the <tt>inbox</tt> folder, the file consumer
notices this and creates a new <tt>FileExchange</tt> that is routed to the <tt>handleOrder</tt>
bean. The bean then processes the File. At this point in time the File is still located in
the <tt>inbox</tt> folder. After the bean completes, and thus the route is completed,
the file consumer will perform the move operation and move the file to the <tt>done</tt>
sub folder.</p>

<p>By default, Camel will move consumed files to the sub-folder <tt>.camel</tt>
relative to where the file was consumed.</p>

<p><b>Available in Camel 1.5.1 or newer</b><br/>
We have introduced a <b>pre</b> move operation to move files <b>before</b>
they are processed. This allows you to mark which files has been scanned as they are moved
to this sub-folder before being processed.<br/>
The following options support pre move:</p>
<ul class="alternate" type="square">
	<li><tt>preMoveNamePrefix</tt></li>
	<li><tt>preMoveNamePostfix</tt></li>
	<li><tt>preMoveExpression</tt></li>
</ul>


<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("file://inbox?preMoveNamePrefix=inprogress/").to("bean:handleOrder");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>You can combine the <b>pre</b> move and the regular move:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("file://inbox?preMoveNamePrefix=inprogress/&amp;moveNamePrefix=../done/").to("bean:handleOrder");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>

<p>So in this situation the file is in the <tt>inprogress</tt> folder when
being processed, and after it's processed it's moved to the <tt>done</tt> folder.</p>

<h3><a name="File-MessageHeaders"></a>Message Headers</h3>

<p>The following message headers can be used to affect the behavior of the component:</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Header </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <tt>org.apache.camel.file.name</tt> </td>
<td class='confluenceTd'> Specifies the output file name (relative to the endpoint directory)
to be used for the output message when sending to the endpoint. If this is not present and
no expression either, then a generated message ID is used as the filename instead.  </td>
</tr>
<tr>
<td class='confluenceTd'> <tt>org.apache.camel.file.name.produced</tt> </td>
<td class='confluenceTd'> New in Camel 1.4: The actual absolute filepath (path + name)
for the output file that was written. This header is set by Camel and its purpose is providing
end-users the name of the file that was written. </td>
</tr>
</tbody></table>


<h3><a name="File-Commongotchaswithfolderandfilenames"></a>Common gotchas
with folder and filenames</h3>

<p>When Camel is producing files (writing files) there are a few gotchas how to set
a filename of your choice. By default Camel will use the message ID as the filename, and since
the message ID is normally a unique generated ID, you will end up with filenames such as:
<tt>ID-MACHINENAME\2443-1211718892437\1-0</tt>. Such a filename is not desired
and therefore best practice is to provide the filename in the message header <tt>org.apache.camel.file.name</tt>.</p>

<p>The sample code below produces files using the message ID as the filename:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("direct:report").to("file:target/reports");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>

<p>To use <tt>report.txt</tt> as the filename you have to do:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("direct:report").setHeader(FileComponent.HEADER_FILE_NAME,
constant("report.txt")).to( "file:target/reports");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>Canel will, by default, try to auto-create the folder if it does not exist, and this
is a bad combination with the UUID filename from above. So if you have:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("direct:report").to("file:target/reports/report.txt");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>

<p>And you want Camel to store in the file <tt>report.txt</tt> and <tt>autoCreate</tt>
is <tt>true</tt>, then Camel will create the folder, <tt>target/reports/report.txt/</tt>.
To fix this, set <tt>autoCreate=false</tt> and create the folder, <tt>target/reports</tt>
manually.</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("direct:report").to("file:target/reports/report.txt?autoCreate=false");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>

<p>With auto-create disabled, Camel will store the report in <tt>report.txt</tt>
as expected.</p>

<h3><a name="File-Fileconsumer%2Cscanningfornewfilesgotcha"></a>File consumer,
scanning for new files gotcha</h3>

<p><b>This only applies to Camel 1.x</b><br/>
The file consumer scans for new files by keeping an internal modified timestamp of the last
consumed file. So if you copy a new file that has an older modified timestamp, Camel will
<b>not</b> pick up this file. This can happen if you are testing and you copy
the same file back to the folder that has just been consumed. To remedy this, modify the timestamp
before copying the file back.</p>

<h3><a name="File-FilenameExpression"></a>Filename Expression</h3>
<p>In Camel 1.5 we have support for setting the filename using an expression. This can
be set either using the <b>expression</b> option or as a string-based <a href="/confluence/display/CAMEL/File+Language"
title="File Language">File Language</a> expression in the <tt>org.apache.camel.file.name</tt>
header. See the <a href="/confluence/display/CAMEL/File+Language" title="File Language">File
Language</a> for some samples.</p>

<h3><a name="File-Samples"></a>Samples</h3>

<h4><a name="File-Readfromadirectoryandwritetoanotherdirectory"></a>Read
from a directory and write to another directory</h4>

<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("file://inputdir/?delete=true").to("file://outputdir")</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>Listen on a directory and create a message for each file dropped there. Copy the
contents to the <tt>outputdir</tt> and delete the file in the <tt>inputdir</tt>.</p>

<h4><a name="File-Readfromadirectoryandprocessthemessageinjava"></a>Read
from a directory and process the message in java </h4>

<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("file://inputdir/").process(new
Processor() {
  public void process(Exchange exchange) throws Exception {
    Object body = exchange.getIn().getBody();
    // do some business logic with the input body
  }
});</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>The body will be a <tt>File</tt> object pointing to the file that was
just dropped into the <tt>inputdir</tt> directory.</p>

<h4><a name="File-Readfilesfromadirectoryandsendthecontenttoajmsqueue"></a>Read
files from a directory and send the content to a jms queue</h4>

<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("file://inputdir/").convertBodyTo(String.class).to("jms:test.queue")</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>By default the file endpoint sends a <tt>FileMessage</tt> which contains
a <tt>File</tt> as body. If you send this directly to the JMS component the JMS
message will only contain the <tt>File</tt> object, not the content. By converting
the <tt>File</tt> to a <tt>String</tt> the message will contain the
actual file contents, which is probably what you want.</p>

<p>The route above using Spring DSL:</p>
<div class="code">
<textarea name="newcodemacro" class="xml:nocontrols:nogutter" rows="10" readonly="readonly">&lt;route&gt;
      &lt;from uri="file://inputdir/"/&gt;
      &lt;convertBodyTo type="java.lang.String"/&gt;
      &lt;to uri="jms:test.queue"/&gt;
   &lt;/route&gt;</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>




<h4><a name="File-Writingtofiles"></a>Writing to files</h4>

<p>Camel is, of course, also able to write files, i.e. produce files. In the sample
below we receive some reports on the SEDA queue that we processes before they are written
to a directory.</p>
<style type="text/css">
@import url(/confluence/download/resources/confluence.ext.code:code/shStyles.css);
</style>
<!--[if IE]>
<style type="text/css">
    .code textarea, .code input { padding: 0 !important; }
</style>
<![endif]-->
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shCore.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushCSharp.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushPhp.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushJScript.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushVb.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushSql.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushXml.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushShell.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushDelphi.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushPython.js"></script>
<script class="javascript" src="/confluence/download/resources/confluence.ext.code:code/shBrushJava.js"></script>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">public
void testToFile() throws Exception {
    MockEndpoint mock = getMockEndpoint("mock:result");
    mock.expectedMessageCount(1);
    mock.expectedFileExists("target/test-reports/report.txt");

    template.sendBody("direct:reports", "This is a great report");

    assertMockEndpointsSatisfied();
}

protected JndiRegistry createRegistry() throws Exception {
    // bind our processor in the registry with the given id
    JndiRegistry reg = super.createRegistry();
    reg.bind("processReport", new ProcessReport());
    return reg;
}

protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        public void configure() throws Exception {
            // the reports from the seda queue is processed by our processor
            // before they are written to files in the target/reports directory
            from("direct:reports").processRef("processReport").to("file://target/test-reports",
"mock:result");
        }
    };
}

private class ProcessReport implements Processor {

    public void process(Exchange exchange) throws Exception {
        String body = exchange.getIn().getBody(String.class);
        // do some business logic here

        // set the output to the file
        exchange.getOut().setBody(body);

        // set the output filename using java code logic, notice that this is done by setting
        // a special header property of the out exchange
        exchange.getOut().setHeader(Exchange.FILE_NAME, "report.txt");
    }

}</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<h4><a name="File-Usingexpressionforfilenames"></a>Using expression for
filenames</h4>

<p>In this sample we want to move consumed files to a backup folder using today's date
as a sub-folder name:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">from("file://inbox?expression=backup/${date:now:yyyyMMdd}/${file:name}").to("...");</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>See <a href="/confluence/display/CAMEL/File+Language" title="File Language">File
Language</a> for more samples.</p>

<h3><a name="File-Writetosubdirectoryusing%7B%7BFileComponent.HEADERFILENAME%7D%7D"></a>Write
to subdirectory using <tt>FileComponent.HEADER_FILE_NAME</tt></h3>
<p>Using a single route, it is possible to write a file to any number of subdirectories.
 If you have a route set up as follows:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">&lt;route&gt;
    &lt;from uri="bean:myBean"/&gt;
    &lt;to uri="file:/rootDirectory"/&gt;
  &lt;/route&gt;</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>You can have <tt>myBean</tt> set the <tt>FileComponent.HEADER_FILE_NAME</tt>
to values such as:</p>
<div class="code">
<textarea name="newcodemacro" class="java:nocontrols:nogutter" rows="10" readonly="readonly">FileComponent.HEADER_FILE_NAME
= hello.txt =&gt; /rootDirectory/hello.txt
FileComponent.HEADER_FILE_NAME = foo/bye.txt =&gt; /rootDirectory/foo/bye.txt</textarea>
<script class="javascript">
    if(!window.newcodemacro_initialised)
    {
        window.newcodemacro_initialised = true;
        window.oldonloadmethod = window.onload;
        window.onload = function(){
            dp.SyntaxHighlighter.HighlightAll('newcodemacro');
            if(window.oldonloadmethod)
            {
                window.oldonloadmethod();
            }
        }
    }

</script>
</div>


<p>This allows you to have a single route to write files to multiple destinations.</p>

<h3><a name="File-SeeAlso"></a>See Also</h3>
<ul>
	<li><a href="/confluence/display/CAMEL/Configuring+Camel" title="Configuring Camel">Configuring
Camel</a></li>
	<li><a href="/confluence/display/CAMEL/Component" title="Component">Component</a></li>
	<li><a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a></li>
	<li><a href="/confluence/display/CAMEL/Getting+Started" title="Getting Started">Getting
Started</a></li>
</ul>

<ul class="alternate" type="square">
	<li><a href="/confluence/display/CAMEL/File+Language" title="File Language">File
Language</a></li>
	<li><a href="/confluence/display/CAMEL/File2" title="File2">File2</a></li>
</ul>

     </div>
     <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href="http://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
       </div>

       <a href="http://cwiki.apache.org/confluence/display/CAMEL/File">View Online</a>
       |
       <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=52931&revisedVersion=92&originalVersion=91">View
Change</a>
              |
       <a href="http://cwiki.apache.org/confluence/display/CAMEL/File?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message