I am using itext7 for PDF manipulation. I am trying to fill form fields by field.setValue method. My _Reader object is filled at constructor level and is used on Adding and Getting form fields. But on Saving form field value, on closing PdfDocument object following exception is caught:
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at iText.IO.Source.OutputStream`1.Write(Byte[] b, Int32 off, Int32 len)
at iText.IO.Source.OutputStream`1.WriteInteger(Int32 value)
at iText.Kernel.Pdf.PdfWriter.WriteToBody(PdfObject pdfObj)
at iText.Kernel.Pdf.PdfWriter.FlushObject(PdfObject pdfObject, Boolean
canBeInObjStm)
at iText.Kernel.Pdf.PdfDocument.FlushObject(PdfObject pdfObject, Boolean
canBeInObjStm)
at iText.Kernel.Pdf.PdfObject.Flush(Boolean canBeInObjStm)
at iText.Kernel.Pdf.PdfPage.Flush(Boolean flushResourcesContentStreams)
at iText.Kernel.Pdf.PdfPage.Flush()
at iText.Kernel.Pdf.PdfDocument.Close()
Code snippet is as following:
using (var memoryStream = new MemoryStream())
{
PdfDocument document = new PdfDocument(_Reader, new PdfWriter(memoryStream));
PdfAcroForm Form = PdfAcroForm.GetAcroForm(document, true);
foreach (PDFField Field in PDFFields)
{
PdfFormField formField = Form.GetField(Field.Name);
switch (Field.Type)
{
case PDF_FIELD_TYPE.TEXTBOX:
if (!string.IsNullOrEmpty(Field.Value))
formField.SetValue(Field.Value);
else
formField.SetValue(string.Empty);
break;
}
}
document.Close();
byte[] PDFBytes = ((MemoryStream)memoryStream).ToArray();
Thanks in advance for help.
Related
I have the following two methods that handles taking photos from a camera and picking photos from a library. They're both similar methods as at the end of each method, I get an ImageSource back from the Stream and I pass it onto another page which has an ImageSource binding ready to be set. These two method work perfectly. The next step now is to save the Image in SQLite so I can show the images in a ListView later on. My question for the XamGods (Xamarin Pros =), what is the best way to save image in SQLite in 2019? I have been in the forums for hours and I still don't have a tunnel vision on what I want to do. I can either
Convert Stream into an array of bytes to save in Sqlite.
Convert ImageSource into an array of bytes (messy/buggy).
Somehow retrieve the actual Image selected/taken and convert that into an array of bytes into SQLite
I'm sorry if my question is general, but Xamarin does not provide a clear-cut solution on how to save images in SQLite and you can only find bits and pieces of solutions throughout the forums listed below.
How to save and retrieve Image from Sqlite
Load Image from byte[] array.
Creating a byte array from a stream
Thank you in advance!
private async Task OnAddPhotoFromCameraSelected()
{
Console.WriteLine("OnAddPhotoFromCameraSelected");
var photo = await Plugin.Media.CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions() { });
var stream = photo.GetStream();
photo.Dispose();
if (stream != null)
{
ImageSource cameraPhotoImage = ImageSource.FromStream(() => stream);
var parms = new NavigationParameters();
parms.Add("image", cameraPhotoImage);
var result = await NavigationService.NavigateAsync("/AddInspectionPhotoPage?", parameters: parms);
if (!result.Success)
{
throw result.Exception;
}
}
}
private async Task OnAddPhotoFromLibrarySelected()
{
Console.WriteLine("OnAddPhotoFromLibrarySelected");
Stream stream = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
if (stream != null)
{
ImageSource selectedImage = ImageSource.FromStream(() => stream);
var parms = new NavigationParameters();
parms.Add("image", selectedImage);
parms.Add("stream", stream);
var result = await NavigationService.NavigateAsync("/AddInspectionPhotoPage?", parameters: parms);
if (!result.Success)
{
throw result.Exception;
}
}
}
As Jason said that you can save image path into sqlite database, but if you still want to save byte[] into sqlite database, you need to convert stream into byte[] firstly:
private byte[] GetImageBytes(Stream stream)
{
byte[] ImageBytes;
using (var memoryStream = new System.IO.MemoryStream())
{
stream.CopyTo(memoryStream);
ImageBytes = memoryStream.ToArray();
}
return ImageBytes;
}
Then load byte[] from sqlite, converting into stream.
public Stream BytesToStream(byte[] bytes)
{
Stream stream = new MemoryStream(bytes);
return stream;
}
For simple sample, you can take a look:
Insert byte[] in sqlite:
private void insertdata()
{
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "sqlite1.db3");
using (var con = new SQLiteConnection(path))
{
Image image = new Image();
image.Content = ConvertStreamtoByte();
var result = con.Insert(image);
sl.Children.Add(new Label() { Text = result > 0 ? "insert successful insert" : "fail insert" });
}
}
Loading image from sqlite:
private void getdata()
{
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "sqlite1.db3");
using (var con = new SQLiteConnection(path))
{
var image= con.Query<Image>("SELECT content FROM Image ;").FirstOrDefault();
if(image!=null)
{
byte[] b = image.Content;
Stream ms = new MemoryStream(b);
image1.Source = ImageSource.FromStream(() => ms);
}
}
}
Model:
public class Image
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string FileName { get; set; }
public byte[] Content { get; set; }
}
We were using the apache file uploads for uploading a file and below code was used for the same.
ServletFileUpload upload = new ServletFileUpload(itemFactory);
List<FileItem> items = upload.parseRequest(request);
Iterator<FileItem> iterator = items.iterator();
while (iterator.hasNext()) {
FileItem item = iterator.next();
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
conf.put(name, value);
} else {
InputStream is = item.getInputStream();
byte[] bytes = ByteStreams.toByteArray(is);
String query = new String(bytes, "UTF-8");
conf.put("test", query);
}
}
But we recently moved to Spring boot and trying to use spring multipart to upload a file.The code which will replace the above code will be
DefaultMultipartHttpServletRequest requestMain = (DefaultMultipartHttpServletRequest) request;
Iterator<String> fileNameIterator = requestMain.getFileNames();
ListIterator<MultipartFile> iterator = null;
while (fileNameIterator.hasNext()) {
multipartFiles = requestMain.getFiles(fileNameIterator.next());
iterator = multipartFiles.listIterator();
while (iterator.hasNext()) {
MultipartFile item = iterator.next();
if (item.isEmpty()) {
// String name = item.getFieldName();
// String value = item.getString();
// conf.put(name, value);
} else {
InputStream is = item.getInputStream();
byte[] bytes = ByteStreams.toByteArray(is);
String query = new String(bytes, "UTF-8");
conf.put("query", query);
}
}
}
But I am not able to figure out how to check if the file has a form field in spring boot.In apache file upload it was achieved using item.isFormField() method.
You don't need to check if the item is form field.
The requestMain.getFiles(fileNameIterator.next()); method will return a MultipartFile so you know is not a form field.
To get the form fields use
requestMain.getParameterMap()
Or, for a specific field use
requestMain.getParameter("field")
I am working on Windows 8 store application. I am new at it.
I am receiving an image in the form of byte array (byte []).
I have to convert this back to Image and display it in Image Control.
so far I have button and Image control on Screen. When I click button, I call following function
private async Task LoadImageAsync()
{
byte[] code = //call to third party API for byte array
System.IO.MemoryStream ms = new MemoryStream(code);
var bitmapImg = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
Windows.Storage.Streams.InMemoryRandomAccessStream imras = new Windows.Storage.Streams.InMemoryRandomAccessStream();
Windows.Storage.Streams.DataWriter write = new Windows.Storage.Streams.DataWriter(imras.GetOutputStreamAt(0));
write.WriteBytes(code);
await write.StoreAsync();
bitmapImg.SetSourceAsync(imras);
pictureBox1.Source = bitmapImg;
}
This is not working properly. any idea?
When I debug, I can see the byte array in ms. but it is not getting converted to bitmapImg.
I found the following on Codeproject
public class ByteImageConverter
{
public static ImageSource ByteToImage(byte[] imageData)
{
BitmapImage biImg = new BitmapImage();
MemoryStream ms = new MemoryStream(imageData);
biImg.BeginInit();
biImg.StreamSource = ms;
biImg.EndInit();
ImageSource imgSrc = biImg as ImageSource;
return imgSrc;
}
}
This code should work for you.
You can try something like that:
public object Convert(object value, Type targetType, object parameter, string language)
{
byte[] rawImage = value as byte[];
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
{
writer.WriteBytes((byte[])rawImage);
// The GetResults here forces to wait until the operation completes
// (i.e., it is executed synchronously), so this call can block the UI.
writer.StoreAsync().GetResults();
}
BitmapImage image = new BitmapImage();
image.SetSource(ms);
return image;
}
}
I found the following answer in another thread (Image to byte[], Convert and ConvertBack). I used this solution in a Windows Phone 8.1 project, not sure about Windows Store apps, but I believe it will work.
public object Convert(object value, Type targetType, object parameter, string culture)
{
// Whatever byte[] you're trying to convert.
byte[] imageBytes = (value as FileAttachment).ContentBytes;
BitmapImage image = new BitmapImage();
InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream();
ms.AsStreamForWrite().Write(imageBytes, 0, imageBytes.Length);
ms.Seek(0);
image.SetSource(ms);
ImageSource src = image;
return src;
}
I have a Controller which returns a FileStreamResult via SharpZipLib (I have tried DotNetZip and there is no difference).
using (var buffer = new MemoryStream())
{
using (var zipStream = new ZipOutputStream(buffer))
{
zipStream.PutNextEntry(new ZipEntry("The Simpsons"));
var bart = Encoding.UTF8.GetBytes("Homer <3 donuts");
zipStream.Write(bart, 0, bart.Length);
zipStream.IsStreamOwner = false;
return File(buffer, MediaTypeNames.Application.Zip, fileName);
}
}
I am trying to unit test this as such:
var controller = new SimpsonsController();
var result = controller.ConfigurationReport(id);
Assert.IsInstanceOf<FileStreamResult>(result);
var streamResult = (FileStreamResult) result;
var zipInputStream = new ZipInputStream(streamResult.FileStream);
Assert.IsNotNull(zipInputStream);
var zipEntry = zipInputStream.GetNextEntry();
Assert.AreEqual("The Simpsons", zipEntry.Name);
Now the unit test fails with:
System.ObjectDisposedException : Cannot access a closed Stream.
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputBuffer.Fill()
at ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputBuffer.ReadLeByte()
at ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputBuffer.ReadLeInt()
at ICSharpCode.SharpZipLib.Zip.ZipInputStream.GetNextEntry()
If I try to directly download via a browser, IIS 500s with a similar stacktrace:
Cannot access a closed Stream.
System.ObjectDisposedException: Cannot access a closed Stream.
at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.Web.Mvc.FileStreamResult.WriteFile(HttpResponseBase response)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
Has anyone tested this kind of stream-based file returning controllers? How did you succeed? Should I simply NOT dispose my classes? Really?
Try this, I think your problem is you are disposing of the stream that is being returned.
public FileStreamResult PDF()
{
MemoryStream buffer = new MemoryStream();
using (var zipStream = new ZipOutputStream(buffer))
{
zipStream.PutNextEntry(new ZipEntry("The Simpsons"));
var bart = Encoding.UTF8.GetBytes("Homer <3 donuts");
zipStream.Write(bart, 0, bart.Length);
zipStream.IsStreamOwner = false;
}
return File(buffer, MediaTypeNames.Application.Zip, fileName);
}
Take a look at this https://stackoverflow.com/a/10891136/985284 and follow other posts from Cheeso for more info.
I am working on GWT RPC. I am facing a problem in retrieving image from my SQL.
Here is my code:
Base64 bas = new Base64();
// sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
UploadfileJpaController up = new UploadfileJpaController();
// this function returns the value in blob field in the form of byte array
byte[] b = up.findUploadfile(n);
String base64Contents = enc.encode(b).replaceAll("\\s+", "");
//String base64 = Base64Utils.toBase64(b);
base64Contents = "data:image/gif;base64,"+base64Contents;
return base64Contents;
But this is not working.. the image is not displayed. Please help :(
You should let a regular servlet take care of returning the image data, and not use GWT-RPC. The servlet should set the proper image/gif header and write the binary data to the response outputstream.
EDIT
This should look somewhat like this
public class FileDownloadServlet extends HttpServletv {
// This method is called by the servlet container to process a GET request.
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// Set content type
resp.setContentType("image/gif");
//Up to you!
byte[] binaryData = getDataFromDbase();
ByteArrayInputStream bis = new ByteArrayInputStream(binaryData);
OutputStream out = resp.getOutputStream();
// Copy the contents of the file to the output stream
byte[] buf = new byte[1024];
int count = 0;
while ((count = bis.read(buf)) >= 0) {
out.write(buf, 0, count);
}
bis.close();
out.close();
}
}
You url is going to be something like
http://server/application/image_servlet?id=123545 where you use the id parameter in the servlet to look up the image. And of course add the servlet to you web.xml. Good luck.