I have a spring boot application with Java 8 in which I can create and download a PDF file with Itext PDF library, in local and development environment this works fine but when I deploy the application in my azure app service I can't download this file, I had a NullPointerException.
2020-11-24T13:04:12.310887019Z: [INFO] ****Downloading PDF file: /home/site/descargas/
2020-11-24T13:04:13.814155878Z: [INFO] *** ERROR : java.lang.NullPointerException
2020-11-24T13:04:13.815304521Z: [ERROR] com.itextpdf.text.DocumentException: java.lang.NullPointerException
2020-11-24T13:04:13.816149053Z: [ERROR] at com.itextpdf.text.pdf.PdfDocument.add(PdfDocument.java:821)
2020-11-24T13:04:13.816580670Z: [ERROR] at com.itextpdf.text.Document.add(Document.java:277)
And my code is:
document = new Document();
FileOutputStream coursesFile = new FileOutputStream(DIRECTORIO_TEMP+"cursos.pdf");
PdfWriter writer = PdfWriter.getInstance(document, coursesFile);
PDFEvent eventoPDF = new PDFEvent();
writer.setPageEvent(eventoPDF);
document.open();
//margenes de documento
document.setMargins(45, 45, 80, 40);
PdfPTable table = new PdfPTable(new float[] {15,35,50,10});
table.setWidthPercentage(100);
table.getDefaultCell().setPaddingBottom(20);
table.getDefaultCell().setPaddingTop(20);
Stream.of("ID", "Área", "Nombre", "Horas").forEach(columnTitle -> {
PdfPCell header = new PdfPCell();
header.setBackgroundColor(COLOR_INFRA);
header.setBorderWidth(1);
header.setHorizontalAlignment(Element.ALIGN_CENTER);
header.setPhrase(new Phrase(columnTitle, fuenteCabecera));
table.addCell(header);
});
for (Curso curso : cursos) {
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(new Phrase(curso.getCodigoCurso(), fuenteNegrita ) );
table.addCell(new Phrase(curso.getAreaBean().getNombre_area(), fuenteNormal ));
table.addCell(new Phrase(curso.getNombreCurso(), fuenteNormal ));
PdfPCell celdaHoras = new PdfPCell( new Phrase(curso.getHoras() + "", fuenteNormal ) );
celdaHoras.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(celdaHoras);
}
document.add(new Paragraph(Chunk.NEWLINE));
document.add(new Paragraph(Chunk.NEWLINE));
document.add(table);
document.close();
coursesFile.close();
The file permission in my Azure app service are:
Newest
Answer For Linux:
I don't know what method you used to deploy the whole process of webapp. However, the descargas folder will not be created automatically in any way.
No matter what method you use to deploy the webapp, it is recommended that you log in to kudu and check the descargas folder and whether the files under the folder exist. It is not recommended to use FTP to upload.
In addition, there should be no concept of D:\ drive and virtual application under Linux. It is recommended to use relative paths in the code to read files.
And
PRIVIOUS
Answer For Windows:
This error occurs because the access path must be wrong. I don't know if your code uses a relative path or an absolute path.
So my advice is:
Use absolute paths to access files.
I have test and it works for me, both in my local and on azure.
The file path like D:\home\site\myfiles\a.pdf .
Use virtual directories to access files
You also can use Virtual Directory to access your file, the path you access by broswer,like https://www.aa.azurewebsites.net/myfiles/a.pdf, and you also can check it by kudu, like D:\home\site\myfiles\a.pdf.
For more details, you can refer to the offical doc,https://learn.microsoft.com/en-us/azure/app-service/configure-common#windows-apps-uncontainerized .
Related
I am using nuGet CsvHelper to write a datatable to a new CSV file. It works fine with path of a physical location Ie C:/temp/mydrop box. But I need it to streamwrite to a Azure Storage container.
when the program gets to here
StreamWriter sw = new StreamWriter(strFilePath, false);
I get the following error:
The filename, directory name, or volume label syntax is incorrect. : 'C:\Users\myuser\source\repos\sample\bin\Debug\net6.0\https://mystorage.blob.core.windows.net/myContainer-processedfiles/myfle.csv''
I am passing in https://mystorage.blob.core.windows.net/myContainer-processedfiles/myfle.csv
I have .net core web API PROJECT. I want to put some static images in this project.I have below code in start up file
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
provider.Mappings[".png"] = "image/png";
// Replace an existing mapping
provider.Mappings[".rtf"] = "application/x-msdownload";
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), #"MyStaticFiles")),
RequestPath = new PathString("/StaticFiles"),
ContentTypeProvider = provider
});
when I run or deployed this web project, i have checked under it has StaticFiles folder has test.png
when I browse for test.tt/StaticFiles/test.png, or test.tt/wwwroot/StaticFiles/test.png or test.tt/wwwroot/StaticFiles/images/test.png
browser is not loading that image, it is displaying white page, where I check on network console of by F12,it is delivering response of type document and json.
My problem is image is not displaying, i have tried more images but not helpful.I am sure there is image,folder in my path.
can you tell how if I browse test.png,direct hitting path to get static file .net core WEB API images?
By default, static files go into the wwwroot in your project root. Calling app.UseStaticFiles(), causes this directory to be served at the base path of the site, i.e. /. As such, a file like wwwroot/images/test.png would be available at /images/test.png (note: without the wwwroot part).
I'm not sure what in the world you're doing with the rest of this code here, but you're essentially adding an additional served directory at [project root]/MyStaticFiles, which will then be served at /StaticFiles. As such, first, test.png would have to actually be in MyStaticFiles, not wwwroot, and then you'd access by requesting /StaticFiles/test.png.
However, there's no need for this other directory. If you simply want to add some additional media types, you can do that via:
services.Configure<StaticFileOptions>(o =>
{
var provider = new FileExtensionContentTypeProvider();
provider.Mappings.Add(".myapp", "application/x-msdownload");
// etc.
o.ContentTypeProvider = provider;
});
And then just use:
app.UseStaticFiles();
Nothing else is required.
I have a simple .Net Core MVC web application that I deploy to Azure. In the application, I am creating a little text file called "test.txt" using File.CreateText(). This works fine on my local PC, but when I deploy it to Azure, I get a strange message: "Could not find file 'D:\home\site\wwwroot\wwwroot\test.txt'."
Indeed, the file does not exist--that's why I'm creating it. Also, it appears someone else on SO is having a similar problem: FileNotFoundException when using System.IO.Directory.CreateDirectory()
Do I not have write permissions? Why is Azure not letting me create the file?
Code (in Startup.cs):
public void Configure(IApplicationBuilder app, IHostingEnvironment env){
using (var sw = File.CreateText(env.WebRootPath + "/test.txt")) { }
}
Screenshot of error:
I found the reason for this error shortly after posting this question, but forgot to post the answer:
It turns out that when you deploy to Azure, your site runs from a temporary directory, which gets wiped and re-created every time you deploy. Because of this, Azure disables the creation and editing of files in the app's directory, since they're just going to get wiped upon your next deployment (it would be nice if the error message Azure displayed was a little more informative).
Therefore, the way to create and edit files on your Azure app and have them persist across deployments is to use one of the following:
Database BLOB storage (simply store your files as byte arrays in a database. doesn't cost any money if you are already using a database)
Azure BLOB storage (store your files to a special cloud on Azure. costs money)
I read this on some site shortly after posting this question but I can't remember where, so I apologize for not having the source.
The best way is use the blog storage AZURE to do this. But you can try save in the root this way:
static void Main(string[] args)
{
// Create a string with a line of text.
string text = "First line" + Environment.NewLine;
// Set a variable to the Documents path.
string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
// Write the text to a new file named "WriteFile.txt".
File.WriteAllText(Path.Combine(docPath, "WriteFile.txt"), text);
// Create a string array with the additional lines of text
string[] lines = { "New line 1", "New line 2" };
// Append new lines of text to the file
File.AppendAllLines(Path.Combine(docPath, "WriteFile.txt"), lines);
}
Reference: https://learn.microsoft.com/pt-br/dotnet/standard/io/how-to-write-text-to-a-file
I have an Azure website configured to write IIS logs to file system. I would like to have a dashboard page within my website where administrators can view reports about traffic on the site, which has been generated by parsing these logs.
I have tried to access the log directory in code by both DirectoryInfo.GetFiles(), and by attempting to connect over FTP using FtpLib.
From outside of Azure, I can connect to the FTP and download the logs, but from code running in the Azure website, I cannot.My assumption is that Azure does not allow outbound FTP traffic from website code.
The folder structure for Azure (by inspecting the FTP) looks something like:
Site: /site/wwwroot
Logs: /LogFiles/http/RawLogs
Within the Azure portal you can create virtual directories, but they are only allowed within /site.
Site is running as an Azure Web Site, MVC 4, Integrated pipeline, 64bit, .NET 4.5, and for FTP I am using FtpLib v1.0.1.2. FtpLib fails at Login() with message: Unknown error (0x2ee2)
I am aware that I can change the logging within Azure to log to Blob Storage, however this would result in additional monthly cost. Are there any other options to access these files?
Thanks.
Edit: Have been asked to supply code, here is the FTP version (works locally, not on Azure):
using (var ftp = new FtpConnection("XXXXXXXX.windows.net", "XXXXXXXX", "XXXXXXXX"))
{
ftp.Open();
ftp.Login(); //Fails here
ftp.SetLocalDirectory(Server.MapPath("~/")); //Temp
ftp.SetCurrentDirectory("/LogFiles/http/RawLogs");
foreach (var f in ftp.GetFiles("*.log"))
{
ftp.GetFile(f.Name, f.Name, false);
ftp.RemoveFile(f.Name);
}
}
And here is the file system version:
//var logRoot = Server.MapPath("~/../../LogFiles/http/RawLogs"); //Throws error about traversal outside of site root
//var logRoot = "/LogFiles/http/RawLogs"; //Throws error: Could not find a part of the path 'D:\LogFiles\http\RawLogs'.
var logRoot = "LogFiles/http/RawLogs"; //Throws error: Could not find a part of the path 'D:\Windows\system32\LogFiles\http\RawLogs'.
foreach (var f in new DirectoryInfo(logRoot).GetFiles("*.log"))
{
f.CopyTo(root + f.Name, true);
f.Delete();
}
I see the problem with paths to the log files. AzureWebsites uses C Drive, but in your implementation you are getting D Drive. Use Server.MapPath("~") and then do string manipulations on top of it to get the right ROOT Path. So Root directory will be having two more directories - LogFiles and Site. As you already got the Root directory, append it with LogFiles directory and read all files from there.
When I upload a picture, the file is successfully saved and the path is successfully set. But the uploaded image is not displayed immediately after the form submit. Only when I reload the page, the uploaded image is displayed.
I'm saving the uploaded file as below:
InputStream is;
try {
File file = new File("C:\\****\\*****\\Documents\\NetBeansProjects\\EventsCalendary\\web\\resources\\images\\uploadPhoto.png");
is = event.getFile().getInputstream();
OutputStream os = new FileOutputStream(file);
setUserPhoto("\\EventsCalendary\\resources\\images\\"+file.getName());
byte buf[] = new byte[1024];
int len;
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
os.close();
is.close();
} catch (IOException ex) {
System.out.println(ex.getStackTrace());
}
Why is the uploaded image only displayed after reloading the page and how can I solve this?
You're writing the file straight into the IDE's project folder and your intent seems to save the file in the webapp's deploy folder. This is a bad idea and well due to the following 3 main reasons:
Changes in the IDE's project folder does not immediately get reflected in the server's work folder. There's kind of a background job in the IDE which takes care that the server's work folder get synced with last updates (this is in IDE terms called "publishing"). This is the main cause of the problem you're seeing.
In real world code there are circumstances where storing uploaded files in the webapp's deploy folder will not work at all. Some servers do (either by default or by configuration) not expand the deployed WAR file into the local disk file system, but instead fully in the memory. You can't create new files in the memory without basically editing the deployed WAR file and redeploying it.
Even when the server expands the deployed WAR file into the local disk file system, all newly created files will get lost on a redeploy or even a simple restart, simply because those new files are not part of the original WAR file.
You need to write it to a fixed path outside the project/deploy folder instead. For example, /var/webapp/uploads. Then, to get it to be served by your webapp, just add it as a new web application context to the server.
Based on your previous question, I know that you're using Glassfish 3.1. In this server, it's called a "virtual host". You can configure it at server level in the admin console at http://localhost:4848 > Configuration > HTTP Service > Virtual Servers, or at webapp level by adding the following line to the /WEB-INF/glassfish-web.xml (your IDE should have autogenerated one; note that this file is before Glassfish 3.1 called sun-web.xml, so if you're seeing manuals/blogs/tutorials referencing it, yes it's exactly the same file):
<property name="alternatedocroot_1" value="from=/uploads/* dir=/var/webapp" />
Either way, you should then be able to use http://localhost:8080/contextname/uploads/* to serve those uploaded images from by <img> the usual way.
See also:
How to upload files to server using JSP/Servlet?
Recommended way to save uploaded files in a servlet application (contains a Tomcat configuration example)
Reading/writing a text file in a servlet, where should this file be stored in JBoss? (contains JBoss configuration example)
Simplest way to serve static data from outside the application server in a Java web application