ServletOutputStream byte array to pdf corrupt pdf - spring

I use tomcat 7.0.53, Struts 1.2.7, Spring 3.1.1. This is my code:
File file = new File("C:\\pdf\\" + report.getFileName());
FileOutputStream fos = new FileOutputStream(file);
fos.write(report.getData());
fos.close();
response.addHeader("Content-disposition", "application; filename="
+ report.getFileName());
response.setContentType("application/pdf");
response.setContentLength(report.getData().length);
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(report.getData());
outputStream.flush();
The file I get is right no problem there. But the file I get from response is corrupted. I tried to set encoding to response, tried to turn on spring CharacterEncodingFilter, tomcats SetCharacterEncodingFilter. Nothing helps. Where should I look at?
p.s. this code is in Struts Action execute method

you might want to save the result that you get from your webserver and compare it with the correct pdf. This way you'll see if there are some extra bytes at beginning or end, differences in encoding or whatever else is different.

Remove response.setContentLength(report.getData().length); and try if it works, by doing this you also enable chunked data transmission.

I needed to return a null instead of an ActionForward so Struts knows the response was handled within the action.

I had the similar issue - corrupted binary pic. upon the download.
Then while downloading TXT/XML files, I have noticed few blank lines at the beginning the text body.
Using the suggestion above on JSP, I removed all line breaks in my JSP page which manages the download.
So all jsp and server tags follow in one single line:
<jsp:useBean.. ><%..response. ;response.setStatus(HttpServletResponse.SC_RESET_CONTENT);return; %>
This removed extra blank lines in TXT/XML and solved binary corruption issue as well.
Olaf, thank you for the clue

Related

TagHelper cached output by calling GetChildContentAsync() and Content.GetContent()

According to this article if we use several tag helpers(targeted to the same tag) and in each of them we will use await output.GetChildContentAsync() to recieve html content we will come to the problem with cached output:
The problem is that the tag helper output is cached, and when the WWW tag helper is run, it overwrites the cached output from the HTTP tag helper.
The problem is fixed by using statement like:
var childContent = output.Content.IsModified ? output.Content.GetContent() :
(await output.GetChildContentAsync()).GetContent();
Description of this behaviour:
The code above checks to see if the content has been modified, and if
it has, it gets the content from the output buffer.
The questions are:
1) What is the difference beetween TagHelperOutput.GetChildContentAsync() and TagHelperOutput.Content.GetContent() under the hood?
2) Which method writes result to buffer?
3) What does it mean "cached output": ASP.NET MVC Core caches initial razor markup or html markup as result of TagHelper calling?
Thank in advance!
The explanation of other answer was not clear for me, so i tested it and here is the summary:
await output.GetChildContentAsync(); ⇒ gets the original content inside the tag which is hard coded in the Razor file. note that it will be cached at first call and never changed at subsequent calls, So it does not reflect the changes done by other TagHelpers at runtime!
output.Content.GetContent(); ⇒ should be used only to get content modified by some TagHelper, otherwise it returns Empty!
Usage samples:
Getting the latest content (whether initial razor or content modified by other tag helpers):
var curContent = output.IsContentModified ? output.Content : await output.GetChildContentAsync();
string strContent = curContent.GetContent();

Manually populate an ImageField

I have a models.ImageField which I sometimes populate with the corresponding forms.ImageField. Sometimes, instead of using a form, I want to update the image field with an ajax POST. I am passing both the image filename, and the image content (base64 encoded), so that in my api view I have everything I need. But I do not really know how to do this manually, since I have always relied in form processing, which automatically populates the models.ImageField.
How can I manually populate the models.ImageField having the filename and the file contents?
EDIT
I have reached the following status:
instance.image.save(file_name, File(StringIO(data)))
instance.save()
And this is updating the file reference, using the right value configured in upload_to in the ImageField.
But it is not saving the image. I would have imagined that the first .save call would:
Generate a file name in the configured storage
Save the file contents to the selected file, including handling of any kind of storage configured for this ImageField (local FS, Amazon S3, or whatever)
Update the reference to the file in the ImageField
And the second .save would actually save the updated instance to the database.
What am I doing wrong? How can I make sure that the new image content is actually written to disk, in the automatically generated file name?
EDIT2
I have a very unsatisfactory workaround, which is working but is very limited. This illustrates the problems that using the ImageField directly would solve:
# TODO: workaround because I do not yet know how to correctly populate the ImageField
# This is very limited because:
# - only uses local filesystem (no AWS S3, ...)
# - does not provide the advance splitting provided by upload_to
local_file = os.path.join(settings.MEDIA_ROOT, file_name)
with open(local_file, 'wb') as f:
f.write(data)
instance.image = file_name
instance.save()
EDIT3
So, after some more playing around I have discovered that my first implementation is doing the right thing, but silently failing if the passed data has the wrong format (I was mistakingly passing the base64 instead of the decoded data). I'll post this as a solution
Just save the file and the instance:
instance.image.save(file_name, File(StringIO(data)))
instance.save()
No idea where the docs for this usecase are.
You can use InMemoryUploadedFile directly to save data:
file = cStringIO.StringIO(base64.b64decode(request.POST['file']))
image = InMemoryUploadedFile(file,
field_name='file',
name=request.POST['name'],
content_type="image/jpeg",
size=sys.getsizeof(file),
charset=None)
instance.image = image
instance.save()

File replace in HttpPostedFileBase MVC3

If the file is uploading with the name already in the specified path, it is showing error. I want to replace with the new file. I have placed the error and the code. Please help to replace the existing image.
Error: The process cannot access the file '' because it is being used by another process.
Code:
[HttpPost]
public ActionResult MyUpload(HttpPostedFileBase file)
{
string filePath = string.Empty;
string path = "C:\\";
string filePath = string.Empty;
try
{
if (file != null && file.ContentLength > 0)
{
filePath = path + file.FileName;
file.SaveAs(filePath);
file.InputStream.Dispose();
GC.Collect();
// other operations, where can occur an exception
// (because the uploaded file can have a bad content etc.)
}
}
catch (Exception e)
{
}
}
Based upon what you posted, I would suggest the following:
[HttpPost]
public ActionResult Foo(HttpPostedFileBase file)
{
var path = #"C:\";
var filename = file.FileName;
file.SaveAs(System.IO.Path.Combine(path, filename));
// do stuff here.
return RedirectToAction("Index");
}
I had this very same issue. I had a sub-folder called "files" where I uploaded files using file.SaveAs() ('file' being of type 'HttpPostedFileBase' [using MVC]). After some local investigation and online research, it turns out that an IIS worker thread/process was locking my file. At first I thought {HttpPostedFileBase}.SaveAs() was somehow locking my file. I even tried to (first) close, and then dispose the {HttpPostedFileBase}.InputStream, and that also didn't help. In the end, it wasn't even related to the file upload process at all. After uploading the file (a PDF), I processed it using ITextSharp, but forgot to dispose of the object wrapper (so it was probably sitting in the GC). Because of that, the next file upload failed due to the locked existing file. BTW, I also tried file.InputStream.Dispose(); file.InputStream.Close(); GC.Collect();, but removed them all in the end, and it still works perfectly now. Bottom line, if an IIS Worker process is locking your file, there's probably a good reason - something somewhere in your code you are missing, and it most likely isn't the MVC framework or IIS itself gone rogue. ;) Also, as it turns out, {HttpPostedFileBase}.SaveAs() WILL overwrite files if they exist, so there's no need to delete them first.
One other tip: I read somewhere to watch out who is creating the files based on how your authorization is setup (whether or not you using an IIS process identity, or the logged-in user identity). In some cases, a file may be created by one logged in user, who then becomes the owner, and another file of the same name from a different user may become blocked; might be something to keep in mind in special cases (like intranet based web apps).

Windows Phone webclient caching "issue"?

I am trying to call the same link, but with different values, the issue is that the url is correct containing the new values but when I download it (Webclient.DownloadStringTaskAsync), it gives me the previous calls result.
I have tried adding headers no-cache, and attaching a random value to the call, and ifmodifiedSince header. however it is still not working.
any help will be much appreciated cause I have tried everything.
uri: + "&junk=" + Guid.NewGuid());
client.Headers["Cache-Control"] = "no-cache";
client.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString();
var accessdes = await client.DownloadStringTaskAsync(uri3);
so here my uri3 contains the latest values, but when I hover over accessdes, it contains the result as if I am making a old uri3 call with previous set data.
I saw one friend that was attaching a random GUID to the Url in order to prevent the OS to cache its content. For example:
if the Url were: http://www.ms.com/getdatetime and the OS is caching it.
Our solution was adding a guid for creating "sort of" like a new url, as an example our previous Url would look like: http://www.ms.com/getdatetime?cachebuster=21EC2020-3AEA-4069-A2DD-08002B30309D
(see more about cache buster : http://www.adopsinsider.com/ad-ops-basics/what-is-a-cache-buster-and-how-does-it-work/ )

Clear my cache using cmd command=> ipconfig/dnsflush?

If my computer is the web server for multiple live websites, is there any harm if I type ipconfig/dnsflush in my command prompt editor?
I always got this problem. I embed a flash (swf) in a .html file. Whenever I update the swf, the .html file always use the old swf even if I clear my cache and whatever else.
Is there any ways to have my .html file always get the latest/updated swf file?
Typing ipconfig/dnsflush won't fix your problem, thats flushing the DNS cache, your problem is that your SWF file is being cached by the browser. There are a few ways to stop this. The easiest is probably by adding a random query-string onto the URL of the SWF file in the EMBED/OBJECT tag:
<script type="text/javascript">
<!--
document.write('<object etc ... ');
document.write('<param name="movie" value="filename.swf?r=' + Math.round(Math.random() * 99999) + '">');
document.write(' the other param tags here );
document.write('<embed src="filename.swf?r=' + Math.round(Math.random() * 99999) + '" etc .... </embed>');
document.write('</object>');
//-->
</script>
But be aware that this means your SWF will be downloaded afresh every time, and never from the browser cache. If you don't want this, consider adding a version number in the querystring rather than a random number, and increment this when you want clients to download a new SWF file.
I have a little php snippet that I use to append the unixtime of when i uploaded the file to the server at the end of the flash' url. This way I just upload the new one and everything sorts itself out automagically.

Resources