I'm working on a ASP.NET MVC page to let users upload a Pdf document once they have digitally signed it.
But for some reason the signature is destroyed when uploading the document even when it's graphic representation is properly displayed.
Here is the code I use to upload the file:
$(document).on('click', 'input[value=Upload]', function (e, argument) {
var formdata = new FormData();
for (i = 0; i < document.getElementById('FileBox').files.length; i++) {
formdata.append(document.getElementById('FileBox').files[i].name, document.getElementById('FileBox').files[i]);
}
var url = '#Url.Action("Upload", "Test")'
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var response = $.parseJSON(xhr.response);
alert(response.result);
}
}
});
I'm retrieving the uploaded files in the controller as follows:
Public Function PostedFiles() As List(Of Byte())
Dim retval As New List(Of Byte())
Dim oRequest As HttpRequest = Web.HttpContext.Current.Request
For Each sFileKey As String In oRequest.Files
Dim oFile As HttpPostedFile = oRequest.Files(sFileKey)
If oFile.ContentLength > 0 Then
Dim iLength As Integer = oFile.ContentLength
Dim oBytes(iLength) As Byte
Dim oStream As System.IO.Stream = oFile.InputStream()
oStream.Read(oBytes, 0, iLength)
retval.Add(oBytes)
End If
Next
Return retval
End Function
After persisting the byte arrays in a SQL server database, when I take them back from the database there is no longer any signature, just the graphic representation of it.
Thanks Mkl for your comment, I realize I was getting no signature since the document was displayed in the browser. Opening the persisted file in Acrobat Reader successfully shows the signature.
Related
I'm trying to open a PDF file with print dialog in IE Edge, it works fine in chrome but not in IE
MVC code to return file using Evo Pdf tool:
var restClient = new RestClient(Request.Url.Scheme + "://" + Request.Url.Authority);
var restResponse = restClient.Execute(request);
if (restResponse.StatusCode == HttpStatusCode.OK)
{
htmlModel.HtmlString = restResponse.Content;
byte[] pdfBytes = PdfUtil.GetEvoPdfBytes(htmlModel);
if (pdfBytes != null)
{
return File(pdfBytes, System.Net.Mime.MediaTypeNames.Application.Pdf, htmlModel.PdfName + ".pdf");
}
}
Javascript code to open file with print dialog, below code works in chrome but not IE:
var req = new XMLHttpRequest();
req.open("POST", "/api/HtmlToPdf", true);
req.setRequestHeader("Content-Type", "application/json");
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
console.log(blob.size);
var lin = window.URL.createObjectURL(blob);
// Works in chrome
var mywindow = window.open(lin, "_blank");
mywindow.focus();
mywindow.print();
};
req.send(JSON.stringify(
{
htmlModel: {
ElementSelector: "#div",
PageOrientation: "Portrait",
PdfName: "abc"
}
}));
IE11 does not support URL.createObjectURL(). So your code will not work for IE browser and you will not be able to open the blob with print dialog..
As a work around, you need to use msSaveBlob or msSaveOrOpenBlob for Internet Explorer browser.
These methods allow a user to save the file on the client as if the file had been downloaded from the Internet.
var blobObject = new Blob(["This is sample text..."]);
window.navigator.msSaveOrOpenBlob (blobObject, 'msSaveOrOpenBlob_testFile.txt');
References:
(1) Download a blob from HTTP URL in IE 11
(2) Saving files locally using Blob and msSaveBlob
(3) Blob download is not working in IE
I am using the following code to post data to my api controller
var form = document.createElement('form');
form.action = '/api/reportsapi/exportToCsv';
form.method = 'POST';
form.style.display = 'none';
for (i in data) {
if (data[i] != "") {
var inputElement = document.createElement('textarea');
inputElement.name = i;
inputElement.value = data[i];
form.appendChild(inputElement);
}
}
document.body.appendChild(form);
form.submit();
and my api controller returns a HttpResponseMessage
var csvValidRequestResult = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(csvReport.Data) };
csvValidRequestResult.Content.Headers.ContentType = new MediaTypeHeaderValue("text/comma-separated-values");
csvValidRequestResult.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = csvReport.FileName };
return csvValidRequestResult;
all this works fine. A file with data is downloaded when the above scripts hits the controller.
But the problem arises if there is any server side exception, in that case the page gets redirected to the the form's api url.
Is there something I can do to get to know of the error and act accordingly on the client side ?
I'm trying to write a WebApi service that receives a file, does a trivial manipulation, and sends the file back. I'm having issues on sending and/or receiving the file from the service.
The issue I'm having is that the file returned from the service is ~1.5x larger than the manipulated file, e.g. when the file is returned it's like 300kb instead of the 200kb it should be.
I assume its being wrapped and or manipulated somehow, and I'm unsure of how to receive it properly. The code for the WebAPI service and the method that calls the web service are included below
In, the WebApi service, when I hit the line return Ok(bufferResult), the file is a byte[253312]
In the method that calls the web service, after the file is manipulated and returned, following the line var content = stream.Result;, the stream has a length of 337754 bytes.
Web API service code
public ConversionController: APIController{
public async Task<IHttpActionResult> TransformImage()
{
if (!Request.Content.IsMimeMultipartContent())
throw new Exception();
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
var file = provider.Contents.First();
var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
var buffer = await file.ReadAsByteArrayAsync();
var stream = new MemoryStream(buffer);
// [file manipulations omitted;]
// [the result is populated into a MemoryStream named response ]
//debug : save memory stream to disk to make sure tranformation is successfull
/*response.Position = 0;
path = #"C:\temp\file.ext";
using (var fileStream = System.IO.File.Create(path))
{
saveStream.CopyTo(fileStream);
}*/
var bufferResult = response.GetBuffer();
return Ok(bufferResult);
}
}
Method Calling the Service
public async Task<ActionResult> AsyncConvert()
{
var url = "http://localhost:49246/api/conversion/transformImage";
var filepath = "drive/file/path.ext";
HttpContent fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(filepath));
using (var client = new HttpClient())
{
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileContent, "file", "fileName");
//call service
var response = client.PostAsync(url, formData).Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception();
}
else
{
if (response.Content.GetType() != typeof(System.Net.Http.StreamContent))
throw new Exception();
var stream = response.Content.ReadAsStreamAsync();
var content = stream.Result;
var path = #"drive\completed\name.ext";
using (var fileStream = System.IO.File.Create(path))
{
content.CopyTo(fileStream);
}
}
}
}
return null;
}
I'm still new to streams and WebApi, so I may be missing something quite obvious. Why are the file streams different sizes? (eg. is it wrapped and how do I unwrap and/or receive the stream)
okay, to receive the file correctly, I needed to replace the line
var stream = response.Content.ReadAsStreamAsync();
with
var contents = await response.Content.ReadAsAsync<Byte[]>();
to provide the correct type for the binding
so, the later part of the methods that calls the service looks something like
var content = await response.Content.ReadAsAsync<Byte[]>();
var saveStream = new MemoryStream(content);
saveStream.Position = 0;
//Debug: save converted file to disk
/*
var path = #"drive\completed\name.ext";
using (var fileStream = System.IO.File.Create(path))
{
saveStream.CopyTo(fileStream);
}*/
I have a rest API which I am calling to retrieve a PNG image to display on my page.
My Code:
void getProfilePicture(var pic_id) {
request = new HttpRequest();
request.responseType = "blob";
request.onReadyStateChange.listen(onPicture);
// Get Basic Auth credentials
var authorization = 'Basic '+storage.loginData['password'];
// Build JSON
Map reqData = new Map();
reqData['id'] = pic_id.toString();
reqData['type'] = 'WEB_SMALL';
// SEND the request to the server.
var url = sifted.serverAPI+'/api/v1/pictures/getpicture';
request.open('POST', url);
request.withCredentials = false;
request.setRequestHeader('Authorization',authorization);
request.setRequestHeader('Content-Type','application/json');
request.send(json.stringify(reqData));
}
void onPicture(_) {
if (request.readyState == HttpRequest.DONE &&
request.status == 200) {
Blob blob = new Blob(request.response);
FileReader reader = new FileReader();
reader.onLoad.listen((fe) {
ImageElement imgInput = query('#profilepic');
imgInput.src = reader.result;
});
reader.readAsDataUrl(blob);
}
}
It does not work and I get these errors in the Dart editor:
Exception: type 'Blob' is not a subtype of type 'List' of 'blobParts'.
Exception: type 'Blob' is not a subtype of type 'List' of 'blobParts'.
Any suggestions on what I am doing wrong?
Thank you !
The problem is this line:
Blob blob = new Blob(request.response);
The Blob constructor expects a List instead of another Blob (which request.response is in your use case): factory Blob(List blobParts, [String type, String endings])
Just delete the line, and directly call reader.readAsDataUrl(request.response), and it should work.
I am encountering a problem in getting the download prompt. In the below code first am allowing the user to upload a file to compress. Once the file is compressed the user should be provided with the compressed files. But in the below code download prompt doesn't appears neither it shows any error. Please help me by correcting my code
The view code:
function CompressFile(box) {
var file = document.getElementById('fileComp');
if (file.value == "") {
alert("Choose a file to upload");
return false;
}
dhtmlx.modalbox.hide(box);
var fd = new FormData();
fd.append('file', file.files[0]);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/FileUpload/Compress', true);
xhr.send(fd);
}
The controller code:
public ActionResult Compress(HttpPostedFileBase file)
{
var supportedType = new[] { "pdf" };
var fileExt = System.IO.Path.GetExtension(file.FileName).Substring(1);
var filename = Path.GetFileNameWithoutExtension(file.FileName) ?? "";
if (file.ContentLength > 0 && supportedType.Contains(fileExt))
{
string filePath = Path.Combine(HttpContext.Server.MapPath(_uploadPDF), Path.GetFileName(file.FileName));
file.SaveAs(filePath);
PdfReader reader = new PdfReader(filePath);
string name = DateTime.Now.ToString("ddMM_HHmmss");
name = Server.MapPath(_fileUploadPath + name + ".pdf");
PdfStamper stamper = new PdfStamper(reader, new FileStream(name, FileMode.Create), PdfWriter.VERSION_1_5);
stamper.FormFlattening = true;
stamper.SetFullCompression();
stamper.Close();
string fn = System.IO.Path.GetFileName(name);
return base.File(name, "application/pdf",fn);
}
else
{
return View();
}
}
The problem is that you're using Ajax. You can't download a file through Ajax. You need to do a regular POST to the ActionMethod. That way the browser can send you back the file and prompt the user where he wants to save it.