I am running Eclipse Java EE and tomcat for running my webapp. I used the following code to store an image file to the upload/images/profilepics directory:
public String uploadPhoto() {
try {
//get path to upload photo
String filePath = servletRequest.getSession().
getServletContext().getRealPath("/uploads/profilepics");
System.out.println("Server path:" + filePath);
//creating unique picture name
Map sess = (Map) ActionContext.getContext().get("session");
Integer uid = (Integer) sess.get("uid");
String profilePictureName = uid + "-" +
MyUtilityFunctions.createVerificationUrl() + this.userImageFileName;
//update user record
//tobe done
String imgUrl = filePath + profilePictureName;
ViewProfileModel pofilePictureUpdate = new ViewProfileModel();
pofilePictureUpdate.updateUserPhotoUrl(imgUrl, uid);
//create new File with new path and name
File fileToCreate = new File(filePath, profilePictureName);
//copy file to given location and with given name
FileUtils.copyFile(this.userImage, fileToCreate);
} catch (Exception e) {
e.printStackTrace();
addActionError(e.getMessage());
return INPUT;
}
return SUCCESS;
}
after printing filePath I got the following result:
Server Path: /home/bril/webspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/picvik/uploads/profilepics
Now the problem is, I am not able to get the image or if I give the same url to <img src=""> nothing is getting displayed.
Please correct where I am doing wrong.
There are suggestions:
there are lots of reason, that you shouldn't save user images in this way, just like #DaveNewton mentioned in another question. There
are some post to help you make your decision:
Post1
Post2
My personal opinion is to save them into DB, because you don't want
to let your user lost their images.
If you need access session, you can check out SessionAware. This should be a better way to access session.
You are using tomcat as application container, you can configure the server to use its local installation, which makes you easier to track the problem in this case. check out this picture below
Back to your question, There are different ways to do this:
if you cannot find the image user just uploaded, you can check it
manual, see 3.
Otherwise, you could try <img src="/uploads/profilepics/<s:property
value='profilePictureName'/>"
Or you can get this picture using stream, here is the snippet:
JSP:
<img src="
<s:url var="profilePic" action="customer-image-action">
<s:param name="uid" value="%{uid}"/>
</s:url>
" alt="kunden logo" />
Action:
public String execute() throws Exception {
// filename = somehow(uid);
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
imgPath = request.getSession().getServletContext().getRealPath("/uploads/profilepics/")+filename;
log.debug("context-path: " + imgPath);
try {
inputStream = FileUtils.openInputStream(new File(imgPath));
} catch (IOException e) {
log.error(e.getCause(), e);
}
return SUCCESS;
}
Related
I am targeting Android API 30. My app was storing log file and taking database backup in location "/storage/emulated/0/SpecialDir/". Now I am facing access denied issue while my app was workinng fine previously.
I got an overview about scoped storage and came to know that we have some managed locaitons where we can store our data accordingly. i.e Audio, Video, Images, and Download
My question is What is the solution for existing apps that was previously saving files on "/storage/emulated/0/SpecialDir/".
Can anyone please guide me what should i do.
string dir = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.ToString(), "LogFolder");
if (Directory.Exists(dir))
{
return Path.Combine(dir, "MyLogFile.txt");
}
try
{
string newDirectory = Directory.CreateDirectory(dir).FullName;
path = Path.Combine(newDirectory, "MyLogFile.txt");
System.IO.File.WriteAllText(path, "This is some testing log.");
}
catch (Exception ex)
{
string msg = ex.Message;
}
The above code is used to make 'LogFolder' if not exist and 'MyLogFile' as well. What changes do i needed to make it compatiable to Android 10. Thankyou
In Android 10, Google has introduced a new feature for external Storage. Its name is Scoped Storage. Google officially translates it as partitioned Storage, or Scoped Storage.The intent is to limit what programs can do with public directories in external storage. Partitioned storage has no effect on either the internal storage private directory or the external storage private directory.In short, in Android 10, there is no change to private directory reads and writes, and you can still use the File set without any permissions. For reading and writing to public directories, you must use the API provided by MediaStore or the SAF (storage access framework), which means you can no longer use the File set to manipulate public directories at will.
If you set targetSdkVersion above 29,you could try to add below codes into your AndroidManifest.Then you could access the File as before.
<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Update (you could try this for public external storage ):
var path = Android.OS.Environment.GetExternalStoragePublicDirectory("LogFolder").AbsolutePath;
Java.IO.File file = new Java.IO.File(path);
if (!file.Exists())
{
file.Mkdirs();
}
try
{
FileWriter fw = new FileWriter(path + Java.IO.File.Separator + "MyLogFile.txt");
fw.Write("This is some testing log.");
fw.Close();
}
catch (Exception ex)
{
string msg = ex.Message;
}
Update for Android 11:
add MANAGE_EXTERNAL_STORAGE permission in your AndroidManifest.
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
in your activity:
if (Environment.IsExternalStorageManager)
{
var path = Android.OS.Environment.GetExternalStoragePublicDirectory("LogFolder").AbsolutePath;
Java.IO.File file = new Java.IO.File(path);
if (!file.Exists())
{
file.Mkdirs();
}
try
{
FileWriter fw = new FileWriter(path + Java.IO.File.Separator + "MyLogFile.txt");
fw.Write("This is some testing log.");
fw.Close();
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
else
{
StartActivityForResult(new Intent(Settings.ActionManageAllFilesAccessPermission), 0);
}
I'm using the ImageResizer nuget package in my MVC Application to resize an uploaded image and convert it to a JPG. This image should then be uploaded to my Azure storage account. I am receiving an error when I try to upload an image file of:
Access to the path 'C:\Program Files (x86)\IIS
Express\Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.jpg'
is denied
So, I've wired something up wrong, but I want to make sure I'm actually doing this correctly. Here is my code:
CarController
public ActionResult CarImageUpload(HttpPostedFileBase CarImage, string id)
{
//Connect to Azure
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("cardata_AzureStorageConnectionString"));
//Process the Image
try
{
//Create Blob Client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
//Retrieve a reference to a container
CloudBlobContainer blobContainer = blobClient.GetContainerReference("car-" + id);
//Process Image
ImageJob image = new ImageJob(CarImage, blobContainer + ".<ext>",
new Instructions("width=500&format=jpg;mode=max"));
//Create the container if it doesn't already exist
try
{
blobContainer.CreateIfNotExists();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
try
{
image.Build();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
try
{
//Upload to Azure
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(CarImage.FileName);
blob.UploadFromStream(CarImage.InputStream);
CarImage.InputStream.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
return RedirectToAction("Index");
}
View
#(Html.Kendo().Upload()
.Name("CarImage")
.Multiple(false)
.Validation(validation => validation.AllowedExtensions(new string[] { ".gif", ".jpg", ".png" }))
.Events(e => e
.Upload("onFileSync")
.Remove("onFileSync"))
.Async(a => a
.Save("CarImageUpload", "Car")
.Remove("CarImageRemove", "Car")
.AutoUpload(true)))
I think the way I've wired this up is looking for my Azure storage on my local disk, I'm not sure how I can ensure it's looking to Azure instead. Can anyone help me get this working?
Problem is not related to uploading to Azure storage.
See this statement
ImageJob image = new ImageJob(CarImage, blobContainer + ".<ext>",
new Instructions("width=500&format=jpg;mode=max"));
The second parameter of ImageJob is the destination to create the resized image.
So the method is to create a image named blobContainer + ".<ext>" i.e. Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.jpg at IIS working directory C:\Program Files (x86)\IIS Express.
To access C:\Program Files (x86), we need to run IDE as administrator, or we'll get the error Access to the path ... is denied.
Instead of running as administrator, you can write your resized image to MemoryStream.
var memoryStream = new MemoryStream();
ImageJob image = new ImageJob(CarImage, memoryStream,
new Instructions("width=500&format=jpg;mode=max"));
If I understand it correctly, you actually want to upload this resized image to Azure storage. Just change blob.UploadFromStream(CarImage.InputStream); to
memoryStream.Position = 0;
blob.UploadFromStream(memoryStream);
Hello
I would like to get the current url of the page after a click on link. When I click on the link (of the 1rst page), the link open a new page (2nd page), and I want get the url of the 2nd page but when I call GetCurrentUrl(), the method return the url of the first page.
This is my code :
String att = driver.findElement(By.linkText("Lien 2")).getAttribute("href");
driver.findElement(By.linkText("Lien 2")).click(); // Open a the 2nd page
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
String act = driver.getCurrentUrl(); // Return the url of the 1rst page; but I want the 2nd
System.out.println("act "+act+" att "+att);
assertEquals(act, att);
Thanks very much for the help !
Instead of the change to pageloadTimeout(), try manually waiting for the Url to change (this is what I'm doing in my code so thought I'd answer).
Insert the function definition below into your code.
The function prints the current URL in a loop so its helpful to debug any problems.
Change the value "30" in WebDriverWait(driver, 30)) if you want a longer timeout.
Make sure to call the function as follows:
try {
waitForUrl(the-url-you-want-to-wait-for);
} catch (Exception ex) {
//handle exception
}
Function:
/**
* Wait until the current page's URL changes to whatever you specify.
* #param Url The URL you want to wait for.
*/
protected static void waitForUrl(WebDriver driver, final String Url) throws Exception {
try {
(new WebDriverWait(driver, 30)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
System.out.println(d.getCurrentUrl());
return d.getCurrentUrl().toLowerCase().endsWith(Url);
}
});
}
catch (TimeoutException e) {
throw new Exception("Timeout Exception encountered while waiting for URL " + Url + ": \n" + e.getMessage());
}
}
I use this method the get the urls of ressources contain on web page
public InputConnection handleResourceRequest(BrowserFieldRequest request) throws Exception
{
final String url = request.getURL();
return super.handleResourceRequest(request);
}
But, I made request.getURL(); it returns relative url and not the absolute url.
How can I change it to get the absolute URL?
When I run your code, it does return me absolute URLs, even when my web page contained relative links. That said, it wouldn't surprise me if sometimes, it doesn't. I haven't fully tested this code, but I would think you could try something like this.
Basically, you check to see if the URL is absolute, and if not, you assemble an absolute URL by using the parent BrowserField document URL:
ProtocolController controller = new ProtocolController(_browserField) {
public InputConnection handleResourceRequest(BrowserFieldRequest request) throws Exception {
String absoluteUrl = null;
URI uri = URI.create(request.getURL());
if (uri.isAbsolute()) {
absoluteUrl = request.getURL();
} else {
String docUrl = _browserField.getDocumentUrl();
String url = request.getURL();
if (url.startsWith("/")) {
// the URL is relative to the server root
URI docUri = URI.create(docUrl);
absoluteUrl = docUri.getScheme() + "://" + docUri.getHost() + url;
} else {
// the URL is relative to the document URL
absoluteUrl = docUrl + url;
}
}
System.out.println(" requesting: " + absoluteUrl);
return super.handleResourceRequest(request);
}
}
Again, for me, I was getting absolute URLs, so I couldn't easily test the code in the branch where the URL is relative. So, it's possible that I'm dropping a "/" somewhere, or not handling file:/// URLs properly.
But, this is a starting point, to workaround your problem.
is there any way out that we can make the data in text file persistent? everytime a user finishes playing a game, in my program his name and respective score is written to a text file. When the next player comes the previous one gets overwritten. since am writing in write mode, I am not sure whether append mode is supported to save scores of this sort in blackberry...any suggestions are welcome
You should really use the PersistentStore to store this type of information - it's much easier to use and probably more reliable than trying to write files.
However, if you insist on writing files, here's the general code to open a file for appending:
private OutputStream openFileForWriting(String filePath) {
try {
FileConnection fconn = (FileConnection) Connector.open(filePath);
// If no exception is thrown, then the URI is valid, but the file may or may not exist.
if (!fconn.exists()) {
fconn.create(); // create the file if it doesn't exist
}
return fconn.openOutputStream(fconn.fileSize());
} catch (IOException ioe) {
System.out.println("Could not open " + filePath + " for writing");
}
return null;
}