When using ProducerTemplate.sendBodyAndHeader() to send a file using the “file” scheme to its destination, and the file path in the URI contains ampersands, it fails to deliver the file with the following errors.
org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint:
file:///c%7C/IMM_SAN/Marketing/f77333bd-f96f-4873-b846-2f1dc5531a5a/2596/PB&J%20Generic%2007064782/transcoded/21726
due to: Failed to resolve endpoint:
file:///c%7C/IMM_SAN/Marketing/f77333bd-f96f-4873-b846-2f1dc5531a5a/25964/PB&J%20Generic%2007064782/transcoded/21726
due to: Invalid uri syntax: no ? marker however the uri has & parameter separators. Check the uri if its missing a ? marker.
Spending a few days trying the different overloads to send the file send(), sendBody(), sendBodyAndHeader() and even sendBodyAndHeaders().
I tried to UrlEncoder.encode() it before hand and of course a no go.
I even debugged the URISupport.normalizeUri(String uri) from the camel-core source and discovered something interesting. Apparently no amount of encoding will do me any good before sending the body and header because it appears to be doing its own encoding and it appears to be totally incorrect. I think this is a bug in sendBodyAndHeader(). It encodes the ampersand back into the URI before sending it. This is bad. Why are we doing that? We have an application that reads files from one department and are written to a share and another system automatically picking those file up and delivering it when processing on the file is finished.
See below camel URISupport.normalizeUri(String uri) method is encoding the URI here and this puts the ampersand back into the file path.
URI u = new URI(UnsafeUriCharactersEncoder.encode(uri));
So you see no amount of preprocessing on the file path in the URI is going to work at all because sendBodyAndHeader is going to do whatever it feels like doing. I would like to add a new overload to this API to turn off normalization and just send the URI as is. But wanted to check here to see if anybody has any less drastic options. Please note this is a problem when ampersands are in the URI path for file schemes.
ProducerTemplate prod = exchange.getContext().createProducerTemplate();
destPath = destPath.replace(':', '|');
destPath = destPath.replaceAll("\\\\", "/");
destPath = destPath.replaceAll("&", "%26"); // replace the ampersand
String query = "file:///" + destPath;
prod.sendBodyAndHeader(query, exchange.getIn().getBody(), Exchange.FILE_NAME, destFileName);
Use the CamelFileName header to avoid messing up the endpoint URI with the reserved character & if you really need that character in the file path.
This example would put a file into
c:\a&b