Set file name in internal zip file in camel - apache-camel

I am currently working on a file zipping in camel.
I have faced some issues with the internal filename in the ZIP file. I am trying to set up the file name in the header but the file name is set up to my overall zip file (myfilename.zip). After I extracted the zip file and file exists with MessageID.txt. I want to set up a file name for my internal files of zip as well.
Can anyone help me with this?
<to uri="amq:queue:INLET"/> <!--QUEUE TO FILE-->
<setHeader name="FileName">
<simple>myfilename</simple>
</setHeader>
<marshal>
<zipfile/>
</marshal>
<to uri="file:C:/Target/?fileName=${header.FileName}.zip"/>

The header name should be CamelFileName, not FileName.
Per documentation: https://camel.apache.org/components/3.14.x/dataformats/zipfile-dataformat.html#_marshal

Related

Apache Camel - How doneFileName Works

source_dir Have files like: ABC_02022018_162301.CSV, ABC_02022018_231801.CSV, controlFile
<route id="Test">
<from uri="file:source_dir?include=ABC_.*\.CSV&doneFileName=controlFile&delete=true&readLock=changed&readLockTimeout=20000&readLockCheckInterval=5000&eadLockMinLength=0"/>
<log message="${file:name}"/>
**destination directory **
</route>
I am looking here is, route has to check controlFile for every main file. If any main file doesn't have control file, main file shouldn't move from source folder.
In my above code, camel only once checking for control file existence in source folder and moving all the files to destination folder. Can anyone please help on this?
According to the Camel docs (section 'Using 'done' Files'), in order to have one doneFile per main file you need to specify dynamic doneFile names:
it is more common to have one done file per target file. This means
there is a 1:1 correlation. To do this you must use dynamic
placeholders in the doneFileName option. Currently Camel supports the
following two dynamic tokens: file:name and file:name.noext which must
be enclosed in ${}
if you don't, then Camel will consume all files and then delete the doneFile unless noop=true
Short answer: if you define doneFileName dynamically like this "doneFileName=${file:name.noext}.trig" then each file you want to transfer must have a copy with .trig extension.
If you define doneFileName statically like "doneFileName=files.trig" then every file will be moved when files.trig appears.
So you have to think of a unique doneFileName for each file instead of "controlFile" and set it dynamically. Easiest way is to use the actual fileName and add some extension.
Examples:
Imagine this files: file1.txt, file2.txt
and this route from:
from("ftp://admin#localhost/from?password=admin"
+ "&fileName=${file:name}"
+ "&doneFileName=${file:name.noext}.done")
In this case file1.txt will be moved only if file1.done is also present in the same folder. file2.txt will be moved only if file2.done is also present in the same folder.
Now imagine this route:
from("ftp://admin#localhost/from?password=admin"
+ "&fileName=${file:name}"
+ "&doneFileName=controlFile");
In this case both files file1.txt and file2.txt will be moved when files.done file is present in the same folder.

How to get the relative path segment for Apache Camel File2

I'm trying to build a file based integration where files are dumped in one of the subdirectories of a main directory for processing. I need to get the name of the sub-directory to know which client the file is for. So if I have:
/uploads/foo/bar.txt
I need to process that file and know that it's for client "foo". I'm not sure how to get that part and set it as a header for the processor that processes the bar.txt file. I've got it picking up files and processing, now I need to add in this piece.
Anyone have ideas for me?
You can get most of this information in the header of the exchange. In your situation as you are consuming the file the following items are avlable:
CamelFileName: Name of the consumed file as a relative file path with
offset from the starting directory configured on the endpoint.
CamelFileNameOnly: Only the file name (the name with no leading
paths).
CamelFileAbsolute: A boolean option specifying whether the consumed
file denotes an absolute path or not. Should normally be false for
relative paths. Absolute paths should normally not be used but we
added to the move option to allow moving files to absolute paths. But
can be used elsewhere as well.
CamelFileAbsolutePath: The absolute path to the file. For relative
files this path holds the relative path instead.
CamelFilePath: The file path. For relative files this is the starting directory + the relative filename. For absolute files this is the absolute path.
CamelFileRelativePath: The relative path.
CamelFileParent: The parent path.
CamelFileLength: A long value containing the file size.
CamelFileLastModified: A Date value containing the last modified
timestamp of the file.
You can query these headers for the information you are looking for using the following example as guidelines:
<log message ="${header.CamelFileAbsolutePath}"/>
See the file component documents at the Camel website for more details.

dynamic input/output folder location in Camel's file component

As per https://camel.apache.org/file2.html, file component cannot be configured with dynamic input/output folder locations?
Is there any workaround/alternative for the same?
Thanks.
Regards
Senthil Kumar Sekar
For the file consumer
You can use a customer filter as dynamic selection of which directories/files to pickup. But the starting directory is configured once (hardcoded).
For that to change you would need to stop the route, and change the directory, and start the route again - if you want to attempt that direction.
For the file producer
The file name is fully dynamic you can just set a name as the file header you want. See documentation for details.
You can use the header CamelFileName also to dynamically set a directory. Slashes will be turned into directories.
Example: CamelFileName = "directory/dyn_subdirectory_n/myfilename.txt" will be placed into the directory "dyn_subdirectory_n" located in "directory". The filename will be "myfilename.txt".

Copy and rename a file with mule

I'm trying to set up a mule app that consists of two flows.
One that retreives files from an ftp to local folder.
The other one polling the same folder and uploads the file to another FTP-server and also copies
a file from a another local folder, renames the copied file to the same filename as the "FTP-file" but with another extension and also uploads it to the same FTP-server.
I've tried to set a variable with the incomming filename but I don't know how to
copy a templatefile and rename it from a local folder as in the flow below.
Any help is appreciated!
You can just set the outputPattern property on the file endpoint using the variable name.
The file endpoint has the attribute to serve this purpose.
<file:outbound-endpoint path="${destination_path}" outputPattern="[new filename to be given to the file ]" doc:name="File" >
</file:outbound-endpoint>
on a FTP endpoint also the outputPattern attribute can be set to the desired filename.
<ftp:outbound-endpoint host="localhost" port="21" responseTimeout="10000" doc:name="FTP" outputPattern="test.xml"/>
Hope this helps.

How to create a file in distributed system using ant script?

i am working with mqfte. i have to create a empty txt file with the same name as the source file after it is transferred to the destination. How can do this using ant script?
Scenario:
Srcpath: \src\test.dat
destpath: \dest\test.dat
After the file is moved from src path, i need to create a empty file test.dat in the src path using ant script? how can this be done?
Before you transfer the files, you could use the Touch task to create the new empty files matching those you will be transferring (reuse the same fileset) in a temporary directory. After the transfers are complete, you could use the Move task to copy the empty files into your src dir. You could use overwrite="false" in the Move task to ensure that files remaining in the src dir do not get replaced (e.g. if you wanted to be sure to have empty files only for successful transfers).
Here is an example.
<project default="test">
<target name="test">
<touch>
<fileset dir="src">
<include name="test*"/>
</fileset>
<mapper type="regexp" from="(.*)" to="tmp/\1"/>
</touch>
<move todir="dest">
<fileset dir="src">
<include name="test*"/>
<!-- simulate file not transferred -->
<exclude name="test.doc"/>
</fileset>
<globmapper from="test.*" to="result_*.txt"/>
</move>
<move todir="src" overwrite="false">
<fileset dir="tmp"/>
</move>
</target>
</project>
The first move stands in for your transfer. One file (test.doc) is not moved out of the src dir (simulate failed transfer). You can test be creating files with some content in the src dir. After the target completes, the test.doc should still have its original content. The other files should be empty.
In response to your question about the regexp mapper:
<mapper type="regexp" from="(.*)" to="tmp/\1"/>
This captures the whole of the incoming file name into a group...
from="(.*)"
and prepends "tmp/" to that captured group...
to="tmp/\1"
(In regular expression \1 refers to the first captured group in the expression. Groups are defined using parentheses.)
So from src/somefile.txt, we will get somefile.txt as the input file to the mapper, and we translate this to tmp/somefile.txt.

Resources