Play! 2 with Java on heroku, save file temporary - java

At the very begining - sorry for my english.
I'm developing a play-application in java and deploy it to heroku.
I like to create a picture (a QRCode to be precisely), store it temporary and display it on the next page.
I do know about herokus ephemeral filesystem, but if I understand right, on the cedar stack, I am able to create files wherever I like, as long as it's ok, that they won't be stored for a long time. The app just needs to generate a QR, I scan it and the file may be deleted.
It seems as if the file is not created. Any ideas of how I can manage to temporary save and show my QRs?
Controller
public class Application extends Controller {
private static String workingDirectory = "public/images/";
public static Result qrCode() {
String msg = "I am a QR-String";
BufferedImage image = (BufferedImage) QR.stringToImage(msg);
String imgPath = workingDirectory+"posQR.png";
try{
File outputfile = new File(imgPath);
ImageIO.write(image,"png",outputfile);
}catch(IOException e){
e.printStackTrace();
}
return ok(views.html.qrCode.render());
}
}
View qrCode
<img src="#routes.Assets.at("images/posQR.png")">
Edit 1
Stored the image as tempFile an pass it to the view.
On heroku an local the view contains the exact absolute path, but the image won't load.
Any ideas left?
Controller
public class Application extends Controller {
private static String workingDirectory = "public/images/";
public static Result qrCode() {
String msg = "I am a QR-String";
BufferedImage image = (BufferedImage) QR.stringToImage(msg);
File outputfile = null;
String imgPath = workingDirectory+"posQR.png";
try{
outputfile = File.createTempFile("posQR",".png");
ImageIO.write(image,"png",outputfile);
}catch(IOException e){
e.printStackTrace();
}
return ok(views.html.qrCode.render(outputfile.getAbsolutePath()));
}
View qrCode
#(qrPath: String)
...
<img id="qr" src=#qrPath>

Does workingDirectory end with file separator?
String imgPath = workingDirectory+"posQR.png";

This helped me: Play! framework 2.0: How to display multiple image?
Finaly I did it. The trick was not to do src=path but src=getImage(path). Still strange, but now it works.
routes
GET /tmp/*filepath controllers.Application.getImage(filepath: String)
Application
public class Application extends Controller {
public static Result qrCode() {
String msg = "I am a QR-String";
BufferedImage image = (BufferedImage) QR.stringToImage(msg);
File outputfile = null;
try{
outputfile = File.createTempFile("posQR",".png");
ImageIO.write(image,"png",outputfile);
}catch(IOException e){
e.printStackTrace();
}
return ok(views.html.qrCode.render(outputfile.getAbsolutePath()));
}
...
public static Result getImage(String imgPath){
return ok(new File(imgPath));
}
}
view qrCode
#(qrPath: String)
...
<img src="#routes.Application.getImage(qrPath)"/>
Thanks for your help :D

Related

How to get the path of the document inside .jar in spring boot? [duplicate]

This question already has answers here:
Can't Access Resources In Executable Jar
(4 answers)
Closed 3 years ago.
I'm running spring boot application with a jar file.
This application sends a mail alond with attachment. The attachment is the part of the jar file. I'm using the code below to fetch the attachment. I have referred this link Classpath resource not found when running as jar
public boolean sendEmail(String content, String subject, String from, String to, String cc, boolean isAttach, List<String> attachFiles, Session session) {
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from, "XXX"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
if(cc!=null && !cc.equals("")) {
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
}
message.setSubject(subject);
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(content, "text/html; charset=utf8");
// creates multipart
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
if (isAttach) {
// adds attachments
if (!attachFiles.isEmpty()) {
for (String filePath : attachFiles) {
try {
ClassPathResource classPathResource = new ClassPathResource("Brochure.pdf");
InputStream inputStream = classPathResource.getInputStream();
MimeBodyPart attachPart = new MimeBodyPart();
attachPart.attachFile(IOUtils.toString(inputStream));
multipart.addBodyPart(attachPart);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
// sets the multipart as email's content
message.setContent(multipart);
Transport.send(message);
System.out.println("sent email for " + to);
return true;
} catch (MessagingException | UnsupportedEncodingException e) {
System.out.println("email sending failed for " + to);
e.printStackTrace();
// throw new RuntimeException(e);
return false;
}
}
I'm using the getInputStream() function itself in order to search for the file inside the jar file. But I'm getting the following error:
javax.mail.MessagingException: IOException while sending message;
nested exception is:
java.io.FileNotFoundException: Invalid file path
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1365)
at javax.mail.Transport.send0(Transport.java:255)
at javax.mail.Transport.send(Transport.java:124)
at com.inversation.app.integration.service.mail.clients.GenericMailClient.sendEmail(GenericMailClient.java:95)
at com.inversation.app.jobs.CronJob.executeInternal(CronJob.java:62)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.io.FileNotFoundException: Invalid file path
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:152)
at javax.activation.FileDataSource.getInputStream(FileDataSource.java:110)
at javax.activation.DataHandler.writeTo(DataHandler.java:318)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1694)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:996)
at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:561)
at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:84)
at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:901)
at javax.activation.DataHandler.writeTo(DataHandler.java:330)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1694)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1913)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1315)
... 7 more
Before podting this question here i have done research my myside, but still not able to solve the problem. Any help would be appreciated.
I'm able to solve the issue by using below code. Hope it helps others. Refer this issue - Similar issue
attachPart.setDataHandler(new DataHandler(new ByteArrayDataSource(this.getClass().getResourceAsStream("/"+filePath),"application/pdf")));
(Caution: You are hard-coding "Brochure.pdf", and ignoring filePath entirely in your loop. I shall assume you meant to attach each value of filePath.)
As you can see in the documentation for the attachFile method, the String argument must be a valid file name.
Converting the bytes in an InputStream to a String certainly will not result in a file name.
A resource in a .jar is not a file. It’s part of a .jar file, not a separate file.
You will need to set the MimeBodyPart’s content and file name manually, instead of using attachFile:
URL content = GenericMailClient.class.getResource("/" + filePath);
attachPart.setDataHandler(new DataHandler(content));
URI uri = content.toURI();
String path = uri.getPath();
String fileName = path.substring(path.lastIndexOf('/') + 1);
attachPart.setDisposition(Part.ATTACHMENT);
attachPath.setFileName(fileName);
(Do not attempt to use the getFile() method of URL. The getFile() method will not return a valid file name, both because the URL won’t be a file: URL, and because characters which are not allowed to appear directly in URLs (like spaces) will be percent-escaped. On the other hand, the URI class properly parses URI components and returns their unescaped forms.)
I Guess, You need to change the way of reading file using springs ResourceUtils from class path in spring boot application as:
File file = ResourceUtils.getFile("classpath:Brochure.pdf");
InputStream in = new FileInputStream(file);
I am sure, it will work for you
I have used this below code in my projects. Basically, what I do is scan the whole classpath for the file intended if I don't have the exact path. This is to help me in making sure that I don't need to have the file in a specific path.
This is because I encountered the same error as you when I use this line.
getClass().getClassLoader().getResource("Brochure.pdf")
So, I created two functions that takes a filename, and the classpaths included in the jar and recursively searched for the file.
private static File findConfigFile(String paths, String configFilename) {
for (String p : paths.split(File.pathSeparator)) {
File result = findConfigFile(new File(p), configFilename);
if (result != null) {
return result;
}
}
return null;
}
private static File findConfigFile(File path, String configFilename) {
if (path.isDirectory()) {
String[] subPaths = path.list();
if (subPaths == null) {
return null;
}
for (String sp : subPaths) {
File subPath = new File(path.getAbsoluteFile() + "/" + sp);
File result = findConfigFile(subPath, configFilename);
if (result != null && result.getName().equalsIgnoreCase(configFilename)) {
return result;
}
}
return null;
} else {
File file = path;
if (file.getName().equalsIgnoreCase(configFilename)) {
return file;
}
return null;
}
}
Here is an example of my code in action:
import java.io.File;
public class FindResourcesRecursive {
public File findConfigFile(String paths, String configFilename) {
for (String p : paths.split(File.pathSeparator)) {
File result = findConfigFile(new File(p), configFilename);
if (result != null) {
return result;
}
}
return null;
}
private File findConfigFile(File path, String configFilename) {
if (path.isDirectory()) {
String[] subPaths = path.list();
if (subPaths == null) {
return null;
}
for (String sp : subPaths) {
File subPath = new File(path.getAbsoluteFile() + "/" + sp);
File result = findConfigFile(subPath, configFilename);
if (result != null && result.getName().equalsIgnoreCase(configFilename)) {
return result;
}
}
return null;
} else {
File file = path;
if (file.getName().equalsIgnoreCase(configFilename)) {
return file;
}
return null;
}
}
}
Here I have a test case that is coupled with a file "test.txt" in my test/resources folder. The content of said file is:
A sample file
Now, here is my test case:
import org.junit.Test;
import java.io.*;
import static org.junit.Assert.fail;
public class FindResourcesRecursiveTest {
#Test
public void testFindFile() {
// Here in the test resources I have a file "test.txt"
// Inside it is a string "A sample file"
// My Unit Test will use the class FindResourcesRecursive to find the file and print out the results.
File testFile = new FindResourcesRecursive().findConfigFile(
System.getProperty("java.class.path"),
"test.txt"
);
try (FileInputStream is = new FileInputStream(testFile)) {
int i;
while ((i = is.read()) != -1) {
System.out.print((char) i);
}
System.out.println();
} catch (IOException e) {
fail();
}
}
}
Now, if you run this test, it will print out "A sample file" and the test will be green.
Now, is this okay with you?

FileNotFoundException (The filename, directory name, or volume label syntax is incorrect)

I am trying to access a file like this:
public class Main {
private static class RemoteAdapter implements SpellcheckerRemoteAdapter {
private Spellchecker spellchecker;
private String fileName = "deutsch.txt";
File file = new File(getClass().getClassLoader().getResource(fileName).getFile());
private RemoteAdapter() {
this.spellchecker = SpellcheckerFactory.createSpellchecker(file);
}
#Override
public boolean check(String word) {
return this.spellchecker.check(word);
}
#Override
public List < String > getProposal(String word) {
return this.spellchecker.getProposal(word);
}
}
public static void main(String[] args) {
System.out.println("Start Server");
try {
Registry registry = LocateRegistry.createRegistry(1088);
SpellcheckerRemoteAdapter adapter = new RemoteAdapter();
UnicastRemoteObject.exportObject(adapter, 0);
registry.rebind(SpellcheckerRemoteAdapter.NAME, adapter);
} catch (RemoteException re) {
System.out.println(re.getMessage());
}
System.out.println("Server is running!");
}
}
When I run my code inside of eclipse it works just fine. But if I export the project as a runnable jar I get the following error:
java.io.FileNotFoundException: file:\C:\Users\Linsane\Desktop\server\SpellcheckerServer.jar!\deutsch.txt (The filename, directory name, or volume label syntax is incorrect)
Although I know that the file is in this location and as I don't build the path myself I don't really get what went wrong.
Try removing getClassLoader() call:
File file = new File(getClass().getResource(fileName).getFile());
You can also open the jar file manually and check if the file is actually packaged into the jar file.
I solved it with the tip of EJP & What's the difference between a Resource, URI, URL, Path and File in Java?
Instead of passing a File like this:
private String fileName = "deutsch.txt";
File file = new File(getClass().getClassLoader().getResource(fileName).getFile());
private RemoteAdapter() {
this.spellchecker = SpellcheckerFactory.createSpellchecker(file);
}
I now pass a URL to the file like this:
private String fileName = "deutsch.txt";
URL url = ClassLoader.getSystemClassLoader().getResource(fileName);
private RemoteAdapter() {
this.spellchecker = SpellcheckerFactory.createSpellchecker(url);
}
Inside of the Spellchecker constructor I then just get an Inputstream of the URL and read from it.

How to properly save frames from mp4 as png files using ExtractMpegFrames.java?

I am trying to get all frames from an mp4 file using the ExtractMpegFrames.java class found here http://bigflake.com/mediacodec/ExtractMpegFramesTest.java.txt
What I currently do is create a temp file (File.createTempFile) in a directory that stores all the frames, create a FileOutputStream and do
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut)
where fOut is the OutputStream with the file.
Currently, the saved images look like this: https://imgur.com/a/XpsV2
Using the Camera2 Api, I record a video and save it as an mp4. According to VLC, the color space for the video is Planar 4:2:0 YUV Full Scale.
Looking around, it seems that each vendor uses different color spaces
https://stackoverflow.com/a/21266510/7351748. I know ffmpeg can conversions with color spaces, but I cannot use it.
I am not sure where to start to solve this issue of the strange output pngs. I am assuming that this is a color space issue, but I can be completely wrong here.
You can get all Frames of Video Using ffmpeg library here is working code.
add dependancy
compile 'com.writingminds:FFmpegAndroid:0.3.2'
to your gradle
private void loadFFMpegBinary() {
try {
if (ffmpeg == null) {
ffmpeg = FFmpeg.getInstance(this);
}
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
// #Override
// public void onFailure() {
// showUnsupportedExceptionDialog();
// }
#Override
public void onSuccess() {
Log.d(TAG, "ffmpeg : correct Loaded");
}
});
} catch (FFmpegNotSupportedException e) {
} catch (Exception e) {
Log.d(TAG, "EXception : " + e);
}
}
here is image extratct method
public void extractImagesVideo() {
File moviesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
);
String filePrefix = "extract_picture";
String fileExtn = ".jpg";
String yourRealPath = getPath(Pick_Video.this, DataModel.selectedVideoUri);
Log.d("selected url", "" + DataModel.selectedVideoUri);
File src = new File(yourRealPath).getAbsoluteFile();
File appDir=new File(moviesDir,"/"+app_name+"/");
if(!appDir.exists())
appDir.mkdir();
DataModel.appDir=appDir;
File dir = new File(appDir, "testVideo");
int fileNo = 0;
while (dir.exists()) {
fileNo++;
dir = new File(moviesDir+"/"+app_name+"/", "testVideo" + fileNo);
}
dir.mkdir();
DataModel.dir = dir;
resultList = new ArrayList<String>(256);
filePath = dir.getAbsolutePath();
File dest = new File(dir, filePrefix + "%03d" + fileExtn);
Log.d(TAG, "startTrim: src: " + src.toString());
Log.d(TAG, "startTrim: dest: " + dest.getAbsolutePath());
String[] complexCommand = { "-i",""+src.toString(),"-qscale:v", "2","-vf", "fps=fps=20/1",dest.getAbsolutePath()};
//"-qscale:v", "2","-vf", "fps=fps=20/1",//
//works fine with speed and
execFFmpegBinary(complexCommand);
}
call this two method on button click event
Comment If Any query.

Reload EditorPane

I found here: what I was searching for but still I have some issues.
This is my action code:
private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) throws IOException {
jEditorPane1.setContentType("text/html");
int returnVal = FileChooser1.showOpenDialog(this);
if (returnVal == FileChooser1.APPROVE_OPTION) {
String image = String.format("<img src=\"%s\">", FileChooser1.getSelectedFile());
jEditorPane1.setText(image);
}
}
Here is a screenshot of what happens, as you can see the image is not loaded.
http://postimg.org/image/agc665ih1/
But if I save the file (with save button) and reopen the same file (with open button), the image is there and is perfectly loaded.
I already tried the .repaint() and .revalidate() methods, but is not working..
Any idea?
This may be problem in setting up path in JEditorPane page. use this:
String image = String.format("<img src=\"%s\">", FileChooser1.getSelectedFile().getPath());
I am assuming that you have already selected appropriate editorKit for JEditorPane.
So now I can answer with my code. I am using this class for the file chooser:
import java.io.File;
import javax.swing.filechooser.FileFilter;
class jpgfilter extends FileFilter {
public boolean accept(File file) {
return file.isDirectory() || file.getAbsolutePath().endsWith(".jpg");
}
public String getDescription() {
return "JPG image (*.jpg)";
}
}
And in my main class I have this:
FileChooser1 = new javax.swing.JFileChooser();
FileChooser1.setDialogTitle("Choose your image:");
FileChooser1.setFileFilter(new jpgfilter());
And that's it.
So I actually found some kind of a solution but I think there is really too much code and that I should do it easily..I actually insert the image and simultaneously save and open the content of the EditorPane as .html file.
The code:
jEditorPane1.setContentType("text/html");
int returnVal = FileChooser1.showOpenDialog(this);
if (returnVal == FileChooser1.APPROVE_OPTION) {
String image = String.format("<img src=\"%s\">", FileChooser1
.getSelectedFile().getPath());
jEditorPane1.setText(image);
String type = jEditorPane1.getContentType();
OutputStream os = new BufferedOutputStream(new FileOutputStream(
"/Library/java_test/temp" + ".html"));
Document doc = jEditorPane1.getDocument();
int length = doc.getLength();
if (type.endsWith("/rtf")) {
// Saving RTF - use the OutputStream
try {
jEditorPane1.getEditorKit().write(os, doc, 0, length);
os.close();
} catch (BadLocationException ex) {
}
} else {
// Not RTF - use a Writer.
Writer w = new OutputStreamWriter(os);
jEditorPane1.write(w);
w.close();
}
String url = "file:///" + "/Library/java_test/temp" + ".html";
jEditorPane1.setPage(url);
}

Android - downloading image from web, saving to internal memory in location private to app, displaying for list item

What I'm trying to do is this: I want my application to download an image from the Internet and save it to the phone's internal memory in a location that is private to the application. If there is no image available for the list item (i.e. it can't be found on the Internet), I want a default placeholder image to display. This is the image that I have defined in my list_item_row.xml file as the default.
In my ListActivity file, I am calling an instance of a CustomCursorAdapter class I have written. It is in CustomCursorAdapter where I am iterating through all the list items and defining what content needs to be mapped to the views, including the image file by trying to read it from internal memory.
I've seen several questions on this subject, but the examples either are specific to external phone memory (e.g. SDCard), involve saving strings instead of images, or involve using Bitmap.CompressFormat to reduce the resolution of the file (which is unnecessary in my case, as these images will be small thumbnails of already-small resolution). Trying to piece together code from each example has been difficult, hence my asking about my specific example.
At the moment, I believe I've written valid code, but no image is displaying for my list items, including the default placeholder image. I don't know if the problem is being caused by invalid download/save code, or invalid read code - it doesn't help that I don't know how to check internal memory to see if the image exists.
Anyways, here's my code. Any help would be greatly appreciated.
ProductUtils.java
public static String productLookup(String productID, Context c) throws IOException {
URL url = new URL("http://www.samplewebsite.com/" + productID + ".jpg");
URLConnection connection = url.openConnection();
InputStream input = connection.getInputStream();
FileOutputStream output =
c.openFileOutput(productID + "-thumbnail.jpg", Context.MODE_PRIVATE);
byte[] data = new byte[1024];
output.write(data);
output.flush();
output.close();
input.close();
}
CustomCursorAdapter.java
public class CustomCursorAdapter extends CursorAdapter {
public CustomCursorAdapter(Context context, Cursor c) {
super(context, c);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ImageView thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
String fileName =
cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_IMAGE_FILE_PATH));
Bitmap bMap = BitmapFactory.decodeFile(fileName);
thumbnail.setImageBitmap(bMap);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.list_item_row, parent, false);
bindView(v, context, cursor);
return v;
}
}
it seems that some code is left out, I re-wrote it like this:
ProductUtils.java
public static String productLookup(String productID, Context c) throws IOException {
URL url = new URL("http://www.samplewebsite.com/" + productID + ".jpg");
InputStream input = null;
FileOutputStream output = null;
try {
String outputName = productID + "-thumbnail.jpg";
input = url.openConnection().getInputStream();
output = c.openFileOutput(outputName, Context.MODE_PRIVATE);
int read;
byte[] data = new byte[1024];
while ((read = input.read(data)) != -1)
output.write(data, 0, read);
return outputName;
} finally {
if (output != null)
output.close();
if (input != null)
input.close();
}
}
Looks like simply referring to the image file name when trying to read it was not enough, and I had to call getFilesDir() to get the path of the file storage. Below is the code I used:
String path = context.getFilesDir().toString();
String fileName = cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_PRODUCT_ID));
if (fileName != null && !fileName.equals("")) {
Bitmap bMap = BitmapFactory.decodeFile(path + "/" + fileName);
if (bMap != null) {
thumbnail.setImageBitmap(bMap);
}
}
void writeToFile(Bitmap _bitmapScaled)
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
_bitmapScaled.compress(Bitmap.CompressFormat.PNG, 40, bytes);
try{
File f;
//you can create a new file name "test.jpg" in sdcard folder.
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
f =new File(android.os.Environment.getExternalStorageDirectory(),"FamilyLocator/userimages/"+imageName);
else
f = new File(Environment.getDataDirectory(),"FamilyLocator/userimages/"+imageName);
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
// remember close de FileOutput
fo.close();
}catch(Exception e){e.printStackTrace();}
}

Categories