User will upload .htm file and that uploaded file i have to convert to .jsp .
User will give me plain html file only with design and required fields. When he will upload I have to parse ans copy all html content also i have to add additional scripts and jstl code in jsp file. Is there any easy way to do this.
Thanks in advance
Handle it through file extension through servlet.
private String extractFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
String[] items = contentDisp.split(";");
for (String s : items) {
if (s.trim().startsWith("filename")) {
String cccfileName = s.substring(s.indexOf("=") + 2, s.length() - 1);
return cccfileName.substring(cccfileName.lastIndexOf("."), cccfileName.length());
}
}
return "";
}
Use it like String fileNameExt = extractFileName(part); and change the file extension to .jsp, it should work.
Related
I am using an Azure Function that has a HTTP trigger with a route parameter {id} which is the fileId of the JSON file I want to read.
I am using a Blob Input Binding to bind where my JSON files are stored. The JSON files are stored in a container called "conversations" and then in a folder called "Conversation".
An example of a file route is "https://<STORAGE_ACCOUNT_NAME>/conversations/Conversation/8da3d7ad3e35273-1aWpKU4rVghHiTaYkjOjVC-eu%7C0000000.json"
Below is my code.
public static class GetConvo
{
[FunctionName("GetConvo")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "getConvo/{id}")] HttpRequest req,
[Blob("conversations/{id}", FileAccess.Read, Connection = "AzureWebJobsStorage")] string json,
ILogger log, string id)
{
log.LogInformation($"File name: {id}");
if (json == null)
{
log.LogInformation($"File {id} not found");
return new NotFoundResult();
}
else
{
log.LogInformation($"Content: {json}");
}
return new OkObjectResult(JsonConvert.DeserializeObject<Message>(json));
The above code works if I move a JSON file to outside the "Conversation" folder, I can access it and receive a 200OK code.
I have tried changing the Blob input binding path to "conversations/Conversation/{id}" as below but that returns a 404 code.
[FunctionName("GetConvo")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "getConvo/{id}")] HttpRequest req,
[Blob("conversations/Conversation/{id}", FileAccess.Read, Connection = "AzureWebJobsStorage")] string json,
ILogger log, string id)
Is this a blob input path problem?
How would I read JSON files that are in a folder in a blob container using an azure function?
#AjgB, yes the Blob path is incorrect. You need to provide the file extension.
Lets say the file is placed directly in your 'conversations' folder. Then your BLOB input bindings should be -
[Blob("conversations/{id}.json", FileAccess.Read, Connection = "AzureWebJobsStorage")] string json
Note the .json in the blob path
I found out what my error was.
The blob input path was correct. It was a URL encoding problem for:
https://<STORAGE_ACCOUNT_NAME>/conversations/Conversation/8da3d7ad3e35273-1aWpKU4rVghHiTaYkjOjVC-eu%7C0000000.json
The % was not recognised and required; putting 25 after the % resolved this error:
https://<STORAGE_ACCOUNT_NAME>/conversations/Conversation/8da3d7ad3e35273-1aWpKU4rVghHiTaYkjOjVC-eu%257C0000000.json
Sending a POST request (Apache httpclient, here Kotlin source code):
val httpPost = HttpPost("http://localhost:8000")
val builder = MultipartEntityBuilder.create()
builder.addBinaryBody("file", File("testFile.zip"),
ContentType.APPLICATION_OCTET_STREAM, "file.ext")
val multipart = builder.build()
httpPost.entity = multipart
val r = httpClient.execute(httpPost)
r.close()
I receive the request in my post handler as a via spark-java Request-object. How do I retrieve the original file (plus the file name as a bonus) from the post request? The request.bodyAsBytes() method seems to add some bytes because the body is larger than the original file.
Thanks, Jörg
Near the bottom of Spark's Documentation page there is a section "Examples and FAQ". The first example is "How do I upload something?".
From there, it links further to an example on GitHub.
In short:
post("/yourUploadPath", (request, response) -> {
request.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp"));
try (InputStream is = request.raw().getPart("file").getInputStream()) {
// Use the input stream to create a file
}
return "File uploaded";
});
To access the original file name:
request.raw().getPart("file").getSubmittedFileName()
To handle multiple files or parts, I usually have code similar to the following (assuming only files are included in the multi-part encoded upload):
for (Part part : req.raw().getParts()) {
try (InputStream stream = part.getInputStream()) {
String filename = part.getSubmittedFileName();
// save the input stream to the filesystem, and the filename to a database
}
}
I have a Silverlight application that uses Web API to upload a document that is stored in a Database as a Filestream. Currently it's done by a POST with a Content-Type: application/json. The object containing a byte array of the File along with some metadata about the file is serialized to JSON and posted to the Web API. Web API then saves the byte array as a Filestream to the Database.
Following is a sample of the current request:
{"FileContent":"JVBERi0xLjUNJeLjz9MNCjEwIDAgb2JqDTw8L0xpbmVhcml6ZWQgMS9MIDI3MTg2L08gMTIvRSAyMjYyNi9OIDEvVCAyNjg4NC9IIFsgNDg5IDE2OF0+Pg1lbmRvYmoNICAgICAgICAgICAgICAgICAgDQoyNyAwIG9iag08PC9EZWNvZGVQYXJtczw8L0NvbHVtbnMgNC9QcmVkaWN0b3IgMTIg0K","ProductId":"85c98324-092a-4d10-bab0-03912e437234","OrderId":"7b826322-7526-4a69-b67c-5c88a04f4c60","FileName":"test.pdf","FileType":1,"FileDescription":"test"}
I would like to change this logic to Post as a Content-Type of Multipart. What would be the best way to form my request? Also, what's the best way to structure my Web API Controller to process the Multipart request?
This is a sample for a Multipart upload.
[HttpPost]
[Route("upload")]
public async Task<IHttpActionResult> Upload()
{
MultipartFileData file = null;
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
return UnsupportedMediaType();
}
// initialize path and provider
string root = HttpContext.Current.Server.MapPath("~/App_Data");
if (Directory.Exists(root) == false) Directory.CreateDirectory(root);
var provider = new MultipartFormDataStreamProvider(root);
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
try
{
// we take the first file here
file = provider.FileData[0];
// and the associated datas
int myInteger;
if (int.TryParse(provider.FormData["MyIntergerData"], out myInteger) == false)
throw new ArgumentException("myInteger is missing or not valid.");
var fileContent = File.ReadAllBytes(file.LocalFileName);
// do something with your file!
}
finally
{
// get rid of temporary file
if (file != null)
File.Delete(file.LocalFileName);
}
// successfull!
return NoContent();
}
This is a sample I got from an API of mine. You can have multiple files for each upload (check the provider.FileData array), and different datas inside the provider.FormData array.
For the client side aspect of this I suggest you to check this answer for a sample of a JS call to this API.
Hope it helps!
I have some html files in another directory with some javascripts, images and css. I want to use that files in my site and restrict users to access that index.html link. I used return File method in my controller action but it couldn't open images on that directory so it didn't work. What is the proper solution?Do you have an idea?
ps. (when i debugged code, i saw that js, css and html files could open with proper mime types except jpg or png files)
public ActionResult User(string name)
{
string file = (Server.MapPath(Url.Content("~/Content/Users/" + name)));
string path = Path.Combine(file);
string mime = GetMimeType(path);
return File(path, mime);
}
public string GetMimeType(string fileName)
{
string mimeType = "application/unknown";
string ext = Path.GetExtension(fileName).ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
{
mimeType = regKey.GetValue("Content Type").ToString();
}
return mimeType;
}
Better just qyery the IIS for static content mime types. That way you have a single location where to administer them.
using Microsoft.Web.Administration;
//--- stuff goes on ---//
ServerManager serverManager = new ServerManager();
var config = serverManager.GetApplicationHostConfiguration();
var staticContent = config.GetSection("system.webServer/staticContent");
var mimeMap = staticContent.GetCollection();
var mType =mimeMap.FirstOrDefault(a => (string) a.Attributes["fileExtension"].Value == ".pdf");
return (mType == null) ? "text/plain" : mType["mimeType"];
Make sure that during the debugging process the following values are returned to the image extensions:
.jpg/.jpeg => mime type: image/jpeg,
.png => mime type:image/png
You can use an xml file where each file extension is mapped to its mime type. This will make sure that your system could handle all of the possible extensions. This link has a suggested xml file
EDIT
From what I have learned (from comments by nico_ekito) it is not possible to use ajax call to download a file. The solution is to create a hidden <iframe> that will download the file, described here.
Problem:
The browser doesn't show download dialog. Any browser - ff, opera, chrome, safari, ie.
I read the docs about serving files, found this question and, based on this, wrote:
Controller.response().setContentType("text/csv");
Controller.response().setHeader("Content-Disposition", "attachment;filename=public/export/filename.csv");
Controller.response().setHeader("Cache-control", "private");
return ok(CSV.export(data, filename));
Where CSV is a class:
public class CSV{
public static File export(Map<String, String> data, String filename){
String csv = data.get("data[saveMe]");
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("public/export/" + filename), "UTF-8"));
bw.write(csv);
bw.newLine();
bw.flush();
bw.close();
}catch(UnsupportedEncodingException e){}
catch(FileNotFoundException e){}
catch(IOException e){}
File downloadMe = new File("public/export/" + filename);
return downloadMe;
}
}
On client side, I use dojo to send POST request (I also tried with GET, result is the same):
xhr.post({
url: '/exportData/',
content: {
saveMe: str
}
}).then(function(response){
//do sth
});
Response headers look like that:
Cache-Control private
Content-Disposition attachment;filename=public/export/filename.csv
Content-Type text/csv
Transfer-Encoding chunked
POST tab in firebug shows proper data in proper csv format. To format data with csv style I use dojox/grid/enhanced/plugins/exporter/CSVWriter
I think it is not possible to download a file from an Ajax request, see this question: Allow User to Download File using Ajax
You should either use an iframe as suggested in the question, or use a standard HTML form containing your data, and do a post on this form.