Upload Document to Web API - javascript

First Step: On my MVC project I have a Div that allow to upload a file.
<div id="modalUpload" style="display:none">
Select a file:
<input id="upload" type="file" name="upload" /><br />
Description:
<input id="documentDescription" type="text" /><br />
<input type="button" value="Submit" id="submitUpload" data-bind="click:function(){ $root.upload() }">
</div>
Second Step: In JavaScript I upload the Document to the web API with a POST request: (for example, with the XMLHttpRequest method)
self.upload = function () {
var file = document.getElementById("upload").files[0];
var xhr = new XMLHttpRequest();
xhr.open('post', "/API/document/addDocument/", true);
xhr.send(file);
}
Third Step: This is my addDocument function on the Web API that expects a Document object, like this:
[HttpPost]
[Route("{controller}/addDocument")]
public string Post([FromBody]Document doc)
{
.......
}
My question is, how can I post the Document to the API as a Document object? Is it possible to set the type of the POST data?
On my JavaScript code, I have a Document object:
var Document = function (data) {
this.id = ko.observable(data.id);
this.name= ko.observable(data.name);
this.size= ko.observable(data.zise);
}
But I'm not sure how to connect between them.
When I tried this:
var file = new Document(document.getElementById("upload").files[0]);
I got the following error:
415 (Unsupported Media Type)
Any help would be very much appreciated.

One possible issue is that you'll need to make sure your XHR request declares the correct MIME type in the accept header.
Using XHR directly can be a bit of a pain. You may want to consider using a client-side library (such as jquery) to make things easier and handle any cross-browser inconsistencies.

You could try getting it as an HttpPostedFileBase
[HttpPost]
[Route("{controller}/addDocument")]
public string Post(HttpPostedFileBase doc)
{
//Parse it to a doc and do what you gotta do
}

Finally, I didn't send the document as an object, and this is what I ended up doing,
self.upload = function () {
if (document.getElementById("upload").value != "") {
var file = document.getElementById("upload").files[0];
var filePath = "....";
if (window.FormData !== undefined) {
var data = new FormData();
data.append("file", file);
var encodedString = Base64.encode(filePath);
$.ajax({
type: "POST",
url: "/API/document/upload/" + file.name + "/" + encodedString ,
contentType: false,
processData: false,
data: data,
success: function (result) {
console.log(result);
},
error: function (xhr, status, p3, p4) {
var err = "Error " + " " + status + " " + p3 + " " + p4;
if (xhr.responseText && xhr.responseText[0] == "{")
err = JSON.parse(xhr.responseText).Message;
console.log(err);
}
});
}
}
}
And this is my API function:
[HttpPost]
[Route("{controller}/upload/{fileName}/{filePath}")]
public async Task<HttpResponseMessage> UploadFile(string fileName, string filePath)
{
if (!Request.Content.IsMimeMultipartContent())
{
return Request.CreateErrorResponse(HttpStatusCode.UnsupportedMediaType, "The request doesn't contain valid content!");
}
byte[] data = Convert.FromBase64String(filePath);
filePath = Encoding.UTF8.GetString(data);
try
{
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.Contents)
{
var dataStream = await file.ReadAsStreamAsync();
// use the data stream to persist the data to the server (file system etc)
using (var fileStream = File.Create(filePath + fileName))
{
dataStream.Seek(0, SeekOrigin.Begin);
dataStream.CopyTo(fileStream);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent("Successful upload", Encoding.UTF8, "text/plain");
response.Content.Headers.ContentType = new MediaTypeWithQualityHeaderValue(#"text/html");
return response;
}
return Request.CreateResponse(HttpStatusCode.ExpectationFailed);
}
catch (Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e.Message);
}
}
That works perfectly, I got the idea from here.

Related

How to download the PDF in Jquery ajax call using java

I created a service to download a PDF file.
On my server-side(Java) the PDF is generated successfully. But I am unable to download that on the UI side (Using Jquery Ajax call).
Could anyone please help me with this?
$(document).on('click', '.orderView', function(event){
orderId = $(this).attr('data');
$.ajax({
type : 'GET',
contentType : 'application/json',
url : '../service/purchase/generateInventoryPurchasePdf/'+orderId,
success : function(response) {
console.log("Success");
},
error : function(response) {
console.log("Error :" + response);
}
});
});
Java Code:
#RequestMapping(value = "/generateInventoryPurchasePdf/{purchaseId}", method = RequestMethod.GET)
public ResponseEntity<ByteArrayResource> generateInventoryPurchasePdf(HttpServletResponse response,#PathVariable("purchaseId") Long purchaseId) throws Exception {
PurchaseOrder purchaseOrder = null;
purchaseOrder = purchaseService.findByPurchaseOrderId(purchaseId);
// generate the PDF
Map<Object,Object> pdfMap = new HashMap<>();
pdfMap.put("purchaseOrder", purchaseOrder);
pdfMap.put("purchaseOrderDetail", purchaseOrder.getPurchaseOrderDetail());
pdfMap.put("vendorName", purchaseOrder.getInvVendor().getName());
pdfMap.put("vendorAddrs", purchaseOrder.getInvVendor().getVenAddress().get(0));
File file = util.generatePdf("email/purchasepdf", pdfMap);
MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, file.getName());
System.out.println("fileName: " + file.getName());
System.out.println("mediaType: " + mediaType);
//Path path = Paths.get(file.getAbsolutePath() + "/" + file.getName());
Path path = Paths.get(file.getAbsolutePath());
byte[] data = Files.readAllBytes(path);
ByteArrayResource resource = new ByteArrayResource(data);
return ResponseEntity.ok()
// Content-Disposition
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + path.getFileName().toString())
// Content-Type
.contentType(mediaType) //
// Content-Lengh
.contentLength(data.length) //
.body(resource);
}
mediaUtil class:
public class MediaTypeUtils {
public static MediaType getMediaTypeForFileName(ServletContext servletContext, String fileName) {
// application/pdf
// application/xml
// image/gif, ...
String mineType = servletContext.getMimeType(fileName);
try {
MediaType mediaType = MediaType.parseMediaType(mineType);
return mediaType;
} catch (Exception e) {
return MediaType.APPLICATION_OCTET_STREAM;
}
}
}
PDF Generation code:
public File generatePdf(String templateName, Map<Object, Object> map) throws Exception {
Assert.notNull(templateName, "The templateName can not be null");
Context ctx = new Context();
if (map != null) {
Iterator<Entry<Object, Object>> itMap = map.entrySet().iterator();
while (itMap.hasNext()) {
Map.Entry<Object, Object> pair = itMap.next();
ctx.setVariable(pair.getKey().toString(), pair.getValue());
}
}
String processedHtml = templateEngine.process(templateName, ctx);
FileOutputStream os = null;
String fileName = "POLIST";
try {
final File outputFile = File.createTempFile(fileName, ".pdf",new File(servletContext.getRealPath("/")));
outputFile.mkdir();
os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(processedHtml);
renderer.layout();
renderer.createPDF(os, false);
renderer.finishPDF();
System.out.println("PDF created successfully");
return outputFile;
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
}
}
}
}
I'm not getting any error, PDF generate successfully in the server side. But In UI side not working.
Downloading files via AJAX isn't really a logical thing to do. When you make an AJAX call, the data returned from the server is returned into your page's JavaScript code (in the response callback value), rather than being returned to the browser itself to decide what to do. Therefore the browser has no way to initiate a download, because the browser is not directly in control of the response - your JavaScript code is in control instead.
As you've indicated in your comment below the question, there are workarounds you can use, but really the best approach is simply to use a regular non-AJAX request to download
For instance you could replace your jQuery code with something like
$(document).on('click', '.orderView', function(event){
orderId = $(this).attr('data');
window.open('../service/purchase/generateInventoryPurchasePdf/'+orderId);
});
This will download the document from a new tab without navigating away from the current page.

Download file from FileStream return using React

Hi I have a web api like in the below picture - returning HttpResponseMessage, I am retutning fileStream as content of it, when I am trying to retrieve or log it on console as console.log(response.data)
it shows some other information but not the stream information or array or anything of that sort. Can somebody please help me how can I read or download file that's returned as stream or FileStream using React.
I am not using jQuery. Any help please, a link or something of that sort. I could able to download the file using byte array but need to implement using FileStream, any help please?
[EnableCors("AnotherPolicy")]
[HttpPost]
public HttpResponseMessage Post([FromForm] string communityName, [FromForm] string files) //byte[]
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var removedInvalidCharsFromFileName = removeInvalidCharsFromFileName(files);
var tFiles = removedInvalidCharsFromFileName.Split(',');
string rootPath = Configuration.GetValue<string>("ROOT_PATH");
string communityPath = rootPath + "\\" + communityName;
byte[] theZipFile = null;
FileStreamResult fileStreamResult = null;
using (MemoryStream zipStream = new MemoryStream())
{
using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
foreach (string attachment in tFiles)
{
var zipEntry = zip.CreateEntry(attachment);
using (FileStream fileStream = new FileStream(communityPath + "\\" + attachment, FileMode.Open))
using (Stream entryStream = zipEntry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
theZipFile = zipStream.ToArray();
fileStreamResult = new FileStreamResult(zipStream, "application/zip") { FileDownloadName = $"{communityName}.zip" };
var i = zipStream.Length;
zipStream.Position = 0;
var k= zipStream.Length;
result.Content = new StreamContent(zipStream);
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/zip");
}
//return theZipFile;
return result;
}
Finally implemented by using the FileStreamResult as well maybe some people would be needed this, here is my API code and then I made call to the post method using axios, so here is my React code. In the axios call responseType becomes arraybuffer and the in the blob declaration it becomes the application/octet-stream type, Hence it completes everything, as I have imported the file-saver, I could able to use saveAs method of it. Finally after many efforts and hearing the screaming from PM, yes it is achieved - but that's the life of any Software Programmer.
Here is Web Api code C#:
[EnableCors("AnotherPolicy")]
[HttpPost]
public FileStreamResult Post([FromForm] string communityName, [FromForm] string files) //byte[]
{
var removedInvalidCharsFromFileName = removeInvalidCharsFromFileName(files);
var tFiles = removedInvalidCharsFromFileName.Split(',');
string rootPath = Configuration.GetValue<string>("ROOT_PATH");
string communityPath = rootPath + "\\" + communityName;
MemoryStream zipStream = new MemoryStream();
using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
foreach (string attachment in tFiles)
{
var zipEntry = zip.CreateEntry(attachment);
using (FileStream fileStream = new FileStream(communityPath + "\\" + attachment, FileMode.Open))
{
using (Stream entryStream = zipEntry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
}
zipStream.Position = 0;
return File(zipStream, "application/octet-stream");
}
Then my client side React code is here:
handleDownload = (e) => {
e.preventDefault();
var formData = new FormData();
formData.append('communityname', this.state.selectedCommunity);
formData.append('files', JSON.stringify(this.state['checkedFiles']));
//let env='local';
let url = clientConfiguration['filesApi.local'];
//let tempFiles = clientConfiguration[`tempFiles.${env}`];
//alert(tempFiles);
axios({
method: 'post',
responseType: 'arraybuffer', //Force to receive data in a Blob Format
url: url,
data: formData
})
.then(res => {
let extension = 'zip';
let tempFileName = `${this.state['selectedCommunity']}`
let fileName = `${tempFileName}.${extension}`;
const blob = new Blob([res.data], {
type: 'application/octet-stream'
})
saveAs(blob, fileName)
})
.catch(error => {
console.log(error.message);
});
};
this event is called when button is clicked or form submitted. Thanks for all the support the SO has given - thanks a lot.

getJSON - How to print out the result, and how to retrieve input?

I implemented some java functions. Now I have to present the result to the user via html.
public Object post()
{
responseHeaders.put("Content-Type", "application/json");
try
{
final User user = UC0_Login.getLoggedInUser(this);
List<Measurement> mylist = MeasurementService.getMeasurementsbyPatient(user.getUsername().toString());
for(int i = 0; i < mylist.size(); i++) {
Measurement mesPatient = mylist.get(i);
DownloaderService.saveTxt(mesPatient);
// System.out.println("Test Name: " + mesPatient.getRequest().getPatient().getFirst_name().toString());
}
}
catch(HttpException x)
{
x.printStackTrace();
this.statusCode = x.getStatusCode();
return "{ \"success\": false }";
}
catch(Exception x)
{
x.printStackTrace();
this.statusCode = StatusCode.SERVER_ERROR_500;
return "{ \"success\": false }";
}
String property = "java.io.tmpdir";
String tempDir = System.getProperty(property);
String result = "Your measurements have been saved at" + tempDir;
return result;
}
There I implemented post(), in a Java class. I also created a HttpServer in the background. As shown in the code, I return a String. How can I print out that string in HTML? And how can I get input (for example an integer) from HTML into for example a get() function? Thank you!!!
If you are basically looking for AJAX request and response, here is a good source to learn how to.
https://blog.garstasio.com/you-dont-need-jquery/ajax/#posting
For example,
HTML
<p id="result"></p>
<form id="frm1" action="/action_page.php">
Your input: <input type="text" id="myInput"><br><br>
<input type="button" onclick="myFunction()" value="Submit">
</form>
JAVASCRIPT
var input = document.getElementById("myInput").value;
xhr = new XMLHttpRequest();
xhr.open('POST', 'Your URL Goes Here');
xhr.onload = function() {
if (xhr.status === 200) {
var response = xhr.responseText;
document.getElementById("result").innerHTML = response;
}
else if (xhr.status !== 200) {
alert('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send(encodeURI('input=' + input)); // Use your API param keys here

Creating zip file in memory out of byte[]. Zip file is never suggest to download

I have a problem with my created zip file. I am using Java 8. I tried to create a zip file out of a byte array, which contains two or more Excel files. . So, I thought everything is alright. I do an ajax call for create and download my file but i don't have the popup for download my zip and i don't have error.
This is my javascript:
function getFile() {
$.ajax({
type: "POST",
url: "/support-web/downloadCSV",
dataType: "json",
contentType: 'application/json;charset=UTF-8',
data: jsonfile,
success: function (data) {
console.log("in sucess");
window.location.href="/support-web/downloadCSV/"+data
},
error:function (xhr, ajaxOptions, thrownError){
console.log("in error")
}
});
}
This is my Controller:
#Controller
#RequestMapping(value = "/downloadCSV")
public class DownloadCSVController {
private static final int BUFFER_SIZE = 4096;
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public void downloadCSV(HttpServletRequest request, HttpServletResponse response, #RequestBody String json)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
int i = 0;
for (String url : parts) {
i++;
URL uri = new URL(url);
HttpURLConnection httpConn = (HttpURLConnection) uri.openConnection();
int responseCode = httpConn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType();
int contentLength = httpConn.getContentLength();
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 9, disposition.length());
}
} else {
// extracts file name from URL
fileName = url.substring(url.lastIndexOf("/") + 1, url.length());
}
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
ZipEntry entry = new ZipEntry(fileName + i + ".csv");
int length = 1;
zos.putNextEntry(entry);
byte[] b = new byte[BUFFER_SIZE];
while ((length = inputStream.read(b)) > 0) {
zos.write(b, 0, length);
}
zos.closeEntry();
inputStream.close();
System.out.println("File downloaded");
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
// this is the zip file as byte[]
int size = baos.toByteArray().length;
byte[] reportContent = baos.toByteArray();
// Write file to response.
OutputStream output = response.getOutputStream();
output.write(reportContent);
output.close();
response.setContentType("application/force-download");
response.setContentLength((int)size);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"test.zip\"");//fileName)
System.out.println("FIN TELECHARGEMENT");
}
}
Problem:
The Browser not should open a download box
The response isn't handled in the error or in the success (ajax)
So what do I wrong or what is the proper way to do this?
In my navigator you can see the response with my file but download box not should open
You need to do two things:
Set headers before writing anything to response stream.
Remove output.close(); you should not do that. Stream is opened and closed by container.
Second point actually not affecting your problem, its just an advice. You can read more about it here Should one call .close() on HttpServletResponse.getOutputStream()/.getWriter()?.

sending file from js to c# web api as base 64. The input is not a valid Base-64 string

as title description.
I'm trying to take a file from js, send it to my web api, and save it as a file on the server.
in my js, i first take the files, an convert them to a object with the file prop, and a base64 string
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.onload = (function (theFile) {
return function (e) {
var newFile = { name : theFile.name,
type : theFile.type,
size : theFile.size,
lastModifiedDate : theFile.lastModifiedDate
}
console.log("e")
console.log(e)
console.log(theFile);
var binaryString = e.target.result;
updloadedFile(newFile, binaryString);
};
})(f);
reader.readAsDataURL(f)
Then i try to post it to my api, Sry there is a little angular mixed in here, but it should work like this anyway
function updloadedFile(file,data)
{
var dummyobj = {
Name: file.name,
Extension: file.type,
Path: "",
DataString: data,
}
$http.post('/api/FileBrowser/UploadedFiles/' + $rootScope.User.App_ID,
JSON.stringify(dummyobj),
{
headers: {
'Content-Type': 'application/json'
}
}
).success(function (data) {
}).error(function (data, status, headers, config) {
});
}
At last at my server, i try to take the DataString an convert it to a file
[HttpPost]
public void UploadedFiles(Int64 id, [FromBody]FileModel value)
{
try
{
var path = HttpContext.Current.Server.MapPath("~/gfx/Files/" + id + "/");
File.WriteAllBytes(path+"\\"+value.Name, Convert.FromBase64String(value.DataString));
}
catch (Exception ex)
{
throw;
}
}
But here it throw a exception with the messeage
The input is not a valid Base-64 string as it contains a non-base 64
character, more than two padding characters, or an illegal character
among the padding characters.
My base-64 string look like this in the web api
data:image/gif;base64,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
You need to remove data:image/gif;base64, before decoding, you can do this in javascript:
updloadedFile(newFile, binaryString.replace('data:image/gif;base64,', ''));
or in C#
File.WriteAllBytes(path+"\\"+value.Name, Convert.FromBase64String(value.DataString.Replace("data:image/gif;base64,", "")));
As jcubic mention, you need to remove the type tag.
A more dynamic way to remove the tag is to split on ;base64, and take last element. Should work for multiple types, instead of being hardcoded for gif files.
const GetBase64 = (file: any) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
var base64 = `${reader.result}`.split(';base64,').pop();
resolve({name: file.name, size: file.size,type: file.type, content: base64})
};
reader.onerror = error => reject(error);
});
};

Categories

Resources