I am currently using TrueZip to add a file to a Zip file that was uploaded to a server via MultiPartFile.
The Problem
Upon appending a file the zip becomes invalid. It can no longer be opened as a zip file.
The Code
Let's start with the relevant code in my upload controller (file is the MultiPartFile):
// Get the file
File dest = null;
TFile zip = null;
try {
// Obtain the file locally, zip, and delete the old
dest = new File(request.getRealPath("") + "/datasource/uploads/" + fixedFileName);
file.transferTo(dest);
// Validate
zip = new TFile(dest);
resp = mls.validateMapLayer(zip);
// Now perform the upload and delete the temp file
FoundryUserDetails userDetails = (FoundryUserDetails) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
UserIdentity ui = userDetails.getUserIdentity();
MapLayer newLayer = new MapLayer();
// generate the prj
mls.generateProjection(resp, dest.getAbsolutePath(), projection);
The method "generateProjection" is where the file is added:
public void generateProjection(UploadMapResponse resp, String fLoc, FoundryCRS proj) throws NoSuchAuthorityCodeException,
FactoryException, IOException {
TFile projFile = new TFile(fLoc, resp.getLayerName() + ".prj");
CoordinateReferenceSystem crs = CRS.decode(proj.getEpsg());
String wkt = crs.toWKT();
TConfig config = TConfig.push();
try {
config.setOutputPreferences(config.getOutputPreferences().set(FsOutputOption.GROW));
TFileOutputStream writer = new TFileOutputStream(projFile);
try {
writer.write(wkt.getBytes());
} finally {
writer.close();
}
} finally {
config.close();
}
}
In order to test if this worked at all I tried it in a simple main:
public static void main(String[] args) {
File f = new File("C:/Data/SierritaDec2011TopoContours.zip");
TFile tf = new TFile(f);
tf.listFiles();
TFile proj = new TFile(f, "test.prj");
TConfig config = TConfig.push();
try {
config.setOutputPreferences(config.getOutputPreferences().set(FsOutputOption.GROW));
TFileOutputStream writer = null;
try {
writer = new TFileOutputStream(proj);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
writer.write("Hello Zip world".getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} finally {
// Pop the current configuration off the inheritable thread local
// stack.
config.close();
}
}
Which, of course, works just fine.
The Question
Does anyone have insight into why, in a web server with a MultiPartFile copied to a local file, the TFileOutputStream fails to write properly?
In a long running server app, you may need to add a call to TVFS.sync() or TVFS.umount() in order to sync or umount archive files. In the case of ZIP files, this will trigger to write the Central Directory at the end of the ZIP file, which is required to form a valid ZIP file.
Please check the Javadoc to decide which call is the best for your use case: http://truezip.java.net/apidocs/de/schlichtherle/truezip/file/TVFS.html
Also, please note that calling TFVS.sync() or TVFS.umount() after each append operation will result in a growing Central Directory to be written each time, which results in huge overhead. So it's worth to consider when exactly you need to do this. Generally speaking this is only required when you want a third party to access the ZIP file. A third party is anyone not interacting with the TrueZIP Kernel for accessing the ZIP file.
Related
I'm using Xamarin.Forms and I am trying to convert an html string to a pdf file using EvoPdfConverter, but the problem is that when I try to do so, on the line htmlToPdfConverter.ConvertHtmlToFile(htmlData, "", myDir.ToString()); in the code snippet below, the app just freezes and does nothing, seems like it wants to connect to the given IP, but it can't, however I don't get any errors or exceptions! not even catch!! does anybody know what I should do to resolve this issue? and here is my code for this:
public void ConvertHtmlToPfd(string htmlData)
{
ServerSocket s = new ServerSocket(0);
HtmlToPdfConverter htmlToPdfConverter = new
HtmlToPdfConverter(GetLocalIPAddress(),(uint)s.LocalPort);
htmlToPdfConverter.TriggeringMode = TriggeringMode.Auto;
htmlToPdfConverter.PdfDocumentOptions.CompressCrossReference = true;
htmlToPdfConverter.PdfDocumentOptions.PdfCompressionLevel = PdfCompressionLevel.Best;
if (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.WriteExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions((Android.App.Activity)Android.App.Application.Context, new String[] { Manifest.Permission.WriteExternalStorage }, 1);
}
if (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.ReadExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions((Android.App.Activity)Android.App.Application.Context, new String[] { Manifest.Permission.ReadExternalStorage }, 1);
}
try
{
// create the HTML to PDF converter object
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
htmlToPdfConverter.LicenseKey = "4W9+bn19bn5ue2B+bn1/YH98YHd3d3c=";
htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
Java.IO.File myDir = new Java.IO.File(root + "/Reports");
try
{
myDir.Mkdir();
}
catch (Exception e)
{
string message = e.Message;
}
Java.IO.File file = new Java.IO.File(myDir, filename);
if (file.Exists()) file.Delete();
htmlToPdfConverter.ConvertHtmlToFile(htmlData, "", myDir.ToString());
}
catch (Exception ex)
{
string message = ex.Message;
}
}
Could you try to set a base URL to ConvertHtmlToFile call as the second parameter? You passed an empty string. That helps to resolve the relative URLs found in HTML to full URLs. The converter might have delays when trying to retrieve content from invalid resources URLs.
I am working on drool dtable xls file with spring.
i have implemented the business rules in xls file using external location and then with the help of kie services i am executing rules.
Following is the code snippet that's how i am loading rules in engine.
at the start of spring initialization i am calling init() method
see below spring configuration.
<bean id="droolsService" class="com.example.drools.DroolsServiceImpl" init-method="init">
Java Code
public void init() {
LOG.info("inside init");
KieSession kieSession;
for (RequestType type : droolsMap.keySet()) {
try {
kieSession = getKieSession(this.getDroolsMap().get(type));
droolsRules.put(type, kieSession);
} catch (Exception e) {
LOG.error("Failed to load kiesession:", e);
throw new RuntimeException(e);
}
}
}
private KieSession getKieSession(final String file) throws DroolsParserException, IOException, BiffException {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
InputStream stream = null;
String drl = null;
String RULE_PATH = "src/main/resources/";
SpreadsheetCompiler converter = new SpreadsheetCompiler();
//Workbook workbook = Workbook.getWorkbook(DroolsServiceImpl.class.getResourceAsStream(file));
Workbook workbook = Workbook.getWorkbook(new FileInputStream(file));
LOG.info("Loading rule file " + file);
for (Sheet sheet : workbook.getSheets()) {
LOG.info("Loading Sheet " + sheet.getName());
stream = new FileInputStream(file);
drl = converter.compile(stream, sheet.getName());
//StringReader reader = new StringReader(drl);
String DRL_FILE = RULE_PATH + sheet.getName() + ".drl";
System.out.println("Drool file added ::: " + DRL_FILE);
kfs.write(DRL_FILE, ResourceFactory.newReaderResource(new StringReader(drl)));
stream.close();
}
KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
KieSessionConfiguration conf = SessionConfiguration.newInstance();
KieSession ksession = kieContainer.newKieSession(conf);
if (kieBuilder.getResults().hasMessages(Message.Level.ERROR)) {
List<Message> errors = kieBuilder.getResults().getMessages(Message.Level.ERROR);
StringBuilder sb = new StringBuilder("Errors:");
for (Message msg : errors) {
sb.append("\n " + msg);
}
try {
throw new Exception(sb.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null)
stream.close();
if (workbook != null)
workbook.close();
}
}
return ksession;
}
Everything working perfect but the problem is i am not able to scan the file changes. If files is modified then i have to restart the server in order to sync the changes.
I have tried listener to load specific init() method after xls dtable has any changes but its not working , same old result is coming.
I have tried kiescanner but i am not able to get the concept.
KieScanner is loading maven kjar so how do i suppose to create kjar.
I just wanted to kie api scan if any changes in the drool file and try to reload whole changes in kiecontainer without server restarting.
Found the answer myself, Posting because it will help someone who needed.
What I did , I have used apache VFS File Monitor-
DefaultFileMonitor fm = new DefaultFileMonitor(new CustomFileListener());
When file will modified , create or get deleted it will call CustomFileListener.
Following is the implementation of CustomFileListener.
import org.apache.commons.vfs2.FileChangeEvent;
import org.apache.commons.vfs2.FileListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.support.XmlWebApplicationContext;
public class CustomFileListener implements FileListener {
private static final Logger LOG = LoggerFactory.getLogger(CustomFileListener.class);
#Override
public void fileCreated(FileChangeEvent fileChangeEvent) throws Exception {
}
#Override
public void fileDeleted(FileChangeEvent fileChangeEvent) throws Exception {
}
#Override
public void fileChanged(FileChangeEvent fileChangeEvent) throws Exception {
LOG.debug(" Under FileChanged Method");
LOG.debug(" File has been changed hence reinitializing init method = " + fileChangeEvent.getFile().getName().getPath());
XmlWebApplicationContext xmlWebApplicationContext =
(XmlWebApplicationContext) ContextLoader.getCurrentWebApplicationContext();
DefaultListableBeanFactory defaultListableBeanFactory =
(DefaultListableBeanFactory) xmlWebApplicationContext.getBeanFactory();
DroolsServiceImpl droolsService = (DroolsServiceImpl) defaultListableBeanFactory.getBean("droolsService");
droolsService.init();
}
}
What i did when the file will change, It will call fileChanged method.
In that i have fetched cached bean(DroolServiceImpl) from ContextLoader.getCurrentWebApplicationContext(); and called its init() method.
So this it will reload whole process and reinitialize the KieModule,KieRepository.
public class RiakSearch {
public static final String RIAK_SERVER = "10.11.172.17";
private static RiakCluster setUpCluster() throws UnknownHostException {
// This example will use only one node listening on localhost:10017
RiakNode node = new RiakNode.Builder()
.withRemoteAddress("10.11.172.17")
.withAuth("administrator", "password#123", null).build();
// This cluster object takes our one node as an argument
RiakCluster cluster = new RiakCluster.Builder(node).build();
// The cluster must be started to work, otherwise you will see errors
cluster.start();
return cluster;
}
public void uploadSchema() {
try {
RiakCluster cluster = setUpCluster();
RiakClient client = new RiakClient(cluster);
System.out.println("Client object successfully created");
File xml = new File("blog_post_schema.xml");
String xmlString = FileUtils.readFileToString(xml);
YokozunaSchema schema = new YokozunaSchema("blog_post_schema",
xmlString);
StoreSchema storeSchemaOp = new StoreSchema.Builder(schema).build();
client.execute(storeSchemaOp);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
RiakSearch obj = new RiakSearch();
obj.uploadSchema();
}
}
java.util.concurrent.ExecutionException: com.basho.riak.client.core.netty.RiakResponseException: Unknown message code: 56
at com.basho.riak.client.core.FutureOperation.get(FutureOperation.java:260)
at com.basho.riak.client.api.commands.CoreFutureAdapter.get(CoreFutureAdapter.java:52)
at com.basho.riak.client.api.RiakCommand.execute(RiakCommand.java:89)
at com.basho.riak.client.api.RiakClient.execute(RiakClient.java:293)
at com.search.RiakSearch.main(RiakSearch.java:64)
Caused by: com.basho.riak.client.core.netty.RiakResponseException: Unknown message code: 56
at com.basho.riak.client.core.netty.RiakResponseHandler.channelRead(RiakResponseHandler.java:52)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:84)
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153)
at io.netty.channel.PausableChannelEventExecutor.invokeChannelRead(PausableChannelEventExecutor.java:86)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:389)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:243)
at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:84)
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153)
at io.netty.channel.PausableChannelEventExecutor.invokeChannelRead(PausableChannelEventExecutor.java:86)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:389)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:956)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:127)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:514)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:471)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:385)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:351)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
at io.netty.util.internal.chmv8.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1412)
at io.netty.util.internal.chmv8.ForkJoinTask.doExec(ForkJoinTask.java:280)
at io.netty.util.internal.chmv8.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:877)
at io.netty.util.internal.chmv8.ForkJoinPool.scan(ForkJoinPool.java:1706)
at io.netty.util.internal.chmv8.ForkJoinPool.runWorker(ForkJoinPool.java:1661)
at io.netty.util.internal.chmv8.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:126)
Make sure that Solr is actually started. By default, search is disabled in Riak 2.x. In order to enable it, change search property in /etc/riak/riak.conf to on. Then restart Riak.
I had the similar issue of
RiakError: 'Unknown message code: 56'
I solved it by changing the parameter of search in the 'riak.conf' file
Here is the file location, if you are using mac and installed via brew
/usr/local/Cellar/riak/2.2.2/libexec/etc/riak.conf
Here are the lines of code i changed from off to on
## To enable Search set this 'on'.
##
## Default: off
##
## Acceptable values:
## - on or off
search = on
I found the documentation explanation a little bit tricky to follow but more or less it is the reference to solve the issue.
I have a Upload component in which I´m supposed to import a xml file in order to parse it.
I´m trying to use the File.createTempFile method to create the file phisically,but something weird is going on.
For example,if I take the file named "test.xml" and use the createTempFile method to create it on the disk,the name of the generate file becomes something like 'test.xml13234xml'.How can I create the file the correct way?
This is expected when using i.e. createTempFile method as it implicitly creates a file with random prefix:
// a part of createTempFile method
private static final SecureRandom random = new SecureRandom();
static File generateFile(String prefix, String suffix, File dir) {
long n = random.nextLong();
if (n == Long.MIN_VALUE) {
n = 0; // corner case
} else {
n = Math.abs(n);
}
return new File(dir, prefix + Long.toString(n) + suffix);
}
which should give something like 'test.xml13234xml'.
If you want to create a file with the correct name and keep it for later use you can rename/move it within uploadSucceeded method.
public class ExampleUpload implements Upload.Receiver, Upload.SucceededListener {
private Upload xmlUpload;
private File tempFile;
public ExampleUpload() {
this.xmlUpload = new Upload("Upload:", this);
this.xmlUpload.addSucceededListener(this);
}
#Override
public OutputStream receiveUpload(String filename, String mimeType) {
try {
tempFile = File.createTempFile(filename, "xml");
tempFile.deleteOnExit();
return new FileOutputStream(tempFile);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
public void uploadSucceeded(SucceededEvent event) {
try {
File destinationFile = new File("c:\\" + event.getFilename());
FileUtils.moveFile(tempFile, destinationFile));
// TODO read and parse destinationFile
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void ZipExtract(string zipfilename, string outputDirectory)
{
using (ZipFile zip = ZipFile.Read(zipfilename))//file not found exception
{
Directory.CreateDirectory(outputDirectory);
zip.ExtractSelectedEntries("name=*.jpg,*.jpeg,*.png,*.gif,*.bmp", " ",
outputDirectory, ExtractExistingFileAction.OverwriteSilently);
}
}
[HttpPost]
public ContentResult Uploadify(HttpPostedFileBase filedata)
{
var path = Server.MapPath(#"~/Files");
var filePath = Path.Combine(path, filedata.FileName);
if (filedata.FileName.EndsWith(".zip"))
{
ZipExtract(filedata.FileName,path);
}
filedata.SaveAs(filePath);
// CreateThumbnail(filePath);
_db.Photos.Add(new Photo
{
Filename = filedata.FileName
});
_db.SaveChanges();
return new ContentResult{Content = "1"};
}
I try to extract the uploaded zip archive and save extracted files in a folder but "file not found" exception happens all the time. What's the mistake?
Have you tried setting a break point here, and see what value filedata.FileName has? (And see if it actually exists on the server.)
if (filedata.FileName.EndsWith(".zip"))
{
ZipExtract(filedata.FileName,path);
}