Avoiding using save() function twice - django-models

I want to use external API for my django application, which sends image to the server and receives back some LaTeX.
My model looks like this:
class Snip(models.Model):
snip = models.FileField(upload_to="snips/") #stored image
latex = models.TextField(default = '') #received text from API
The image has to be stored/saved so URL might be included in JSON sent to the API. But that implies newly uploaded image has to be saved in newly created Snip object and after receiving the requested text back saved again.
My view looks like this:
if file:
temp_snip = Snip() #creating newe object
temp_snip.snip = file
temp_snip.save() #saving image to the database (required for getting image URL)
temp_snip.setLatex() #some magic :)
temp_snip.save() #saving the magic (second field in the model).
My question is:
Is there any simple solution to avoid using save() function twice?

Related

Browser data storage location for "Choose File" button

For web browsers (such as Chrome, IE, or Firefox), when you select a file using a "Choose File" button, where does the file's data get stored?
The file name shows in the browser, but does the data of the file get stored anywhere or is just a link to the file put somewhere, such as in the browser or a temporary file?
To clarify: I want to know where the file's data get's stored BEFORE submitting. JUST after the file is selected from the client's PC an not anything else is done.
After you select a file. I believe the client (browser) just stores a reference to the file location on the user's computer. It takes a combination of js and html to post the file to the server. Via a Multi/form-data Post.
In this case, on the server, you may have to store the file to a temp location of your choosing, until you're able to process it (i.e. transform and/or store to a Datastore).
In newer browsers you can use the FormData object and xhr to post to the server which is a lot cleaner.
This FormData object is used to construct the key/value pairs which form the data payload for the xhr request.
// Create a new FormData object.
var formData = new FormData();
In this case, once the file bytes are posted to the server, you can do whatever you want with that data. Typically I'll store it as a blob in the DB.
This approach will allow you to keep it all in memory. People make the mistake of trying to store on the server file system. In some multipart form post, you might have to do it this way, however.
Here's some of my web api upload code when using XHR.
I've also called this API route using an iframe (ugh!) in order to support IE8 and older. POS browsers!
/// <summary>
/// Upload the facility logo.
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("logo")]
public HttpResponseMessage Logo()
{
int newImageId = -1;
var uploadedFiles = HttpContext.Current.Request.Files;
if (uploadedFiles.Count > 0)
{
var file = uploadedFiles[0];
if (!file.IsImage())
{
// "The uploaded file must be a .jpg, .jpeg, or .png"
return
Request.CreateResponse(HttpStatusCode.UnsupportedMediaType,
"unsupported");
}
var facilityRepository = new FacilityRepository();
var logoBytes =
StreamCopier.StreamToByteArray(file.InputStream, file.ContentLength);
newImageId = facilityRepository.InsertLogoImage(logoBytes);
}
return Request.CreateResponse(HttpStatusCode.OK,
newImageId);
}

pdf.js and protected files not otherwise viewable

I am using the PDF.js library to display PDf files within my site (using the pdf_viewer.js to display documents on-screen), but the PDF files I am displaying are confidential and I need to be able to show them within the site but block non-authorized public folks from being able to view the same files just by typing in theie URLs and seeing them show up right in their browser.
I tried to add the Deny from all line in my htaccess file, but that also of courfse blocked the viewer from showing the docs, so that seems to be a no-go. Clearly anyone could simply look at inspector and see the pdf file that is being read by the viewer, so it seems a direct URL is not going to be secure in any way.
I did read about PDF.js being able to read binary data, but I have no knowledge of how I might read in a PDF in my own file system and prep it for use by the library, eveen if that means it is all a bit slower in loading to get the file contents and prep it on the fly.
Anyone have a solution that allows PDFJS to work without revealing the source PDF URL, or to otherwise read the file using local file calls?
Okay, after some testing, the solution is very easy:
Get the PDF data using an Ajax-called function that can figure out what actual file is to be viewed.
In that PHP file...
Read the file into memory, using fopen and fread normally.
Convert to base64 using the base64_encode
Pass that string back to the calling Javascript.
In the original calling function, use the following to convert the string to a Uint array and then pass that to the PDFJS library...
## The function that turns the base64 string into whatever a Uint8 array is...
function base64ToUint8Array(base64) {
var raw = atob(base64);
var uint8Array = new Uint8Array(raw.length);
for (var i = 0; i < raw.length; i++) {
uint8Array[i] = raw.charCodeAt(i);
}
return uint8Array;
}
## the guts that gets the file data, calls the above function to convert it, and then calls PDF.JS to display it
$.ajax({
type: "GET",
data: {file: <a file id or whatever distinguishes this PDF>},
url: 'getFilePDFdata.php', (the PHP file that reads the data and returns it encoded)
success: function(base64Data){
var pdfData = base64ToUint8Array(base64Data);
## Loading document.
PDFJS.getDocument(pdfData).then(function (pdfDocument) {
## Document loaded, specifying document for the viewer and
## the (optional) linkService.
pdfViewer.setDocument(pdfDocument);
pdfLinkService.setDocument(pdfDocument, null);
});
}
});

How to create url for each file entry in database (liferay) and download it

I have a table that contains a file id and a file content saved as clob type.
Now I want to create a link programmatically for each file and download via it.
How this is possible?
I have created my link but I have no idea how to get file from that link.
String fileUrl = themeDisplay.getPortalURL() + themeDisplay.getPathContext() + "/files/"
+ themeDisplay.getScopeGroupId() + "/Folder/" + HttpUtil.encodeURL(HtmlUtil.unescape(String.valueOf(fileId)));
I assume you have your own service for you custom table (Service created by Liferay Service Builder).
What you can do is that at the page load, you can create the <portlet:resourceURL> links with id as a parameter.
When user clicks this, the serveResource() method will be called. Here, just call your service and get the data by passing id. Take that data and write the data into OutputStream and provide the valid Content-Type.
This should work, as the main purpose of serveResource() is to serve resource! :)

how to clear the file name list after fineUploader (3.5) uploads file

I download fine uploader 3.5, created http handler for a file upload function in my little website . the website is done by asp.net ajax and jquery. it runs at IE9. every time I upload a file, there is a list of file names shown below the load button. if I don't want thme, what should I do?
my code is like this:
html: ...
'<tr><td><div id="jquery-wrapped-fine-uploader"></div></td></tr>...
'ajax/jquery:...
'$('#jquery-wrapped-fine-uploader').fineUploader({
'request: { endpoint: 'xxx.ashx' }
'})
'$('#jquery-wrapped-fine-uploader').on("complete",
'function (event, id, fileName, responseJSON) {
' alert("UPLOAD SUCCESS");
' $.ajax({some ajax calls here});
' })
// WHERE TO PUT this TO CLEAR the UPLOADED FILE LIST??? $('#jquery-wrapped-fine-uploader').fineUploader('reset');
XXX.ashx:
'... public void ProcessRequest (HttpContext context) {
'do some http request work..
'context.Response.ContentType = "text/plain";
'context.Response.Write("{\"success\":true}");
'}
My question is:
I want to completely remove the uploaded file list which shows automatically in green color ( or red if they fail), in order to clear them, I tried to put: $('#jquery-wrapped-fine-uploader').fineUploader('reset'); right after .on('complete'), it's not working, also #jquery-wrapped-fine-uploader seems cached all the time. please help on this.
If you don't want to see the file list at all, you should be using FineUploaderBasic mode instead of using FineUploader mode and then removing all elements in the pre-built UI. FineUploaderBasic mode gives you access to the API, options, and callbacks, but assumes you will be creating your own UI. In other words, FineUploaderBasic mode does not create any DOM elements (except the opaque file input element as a child of your button container, if you supply one). This is all explained (in a great amount of detail) in the documentation.
Start here: http://docs.fineuploader.com

CakePHP how to combine process steps

I am developing a system that allows users to download files, but IF they download a file I want to log this action in a special purpose table (MySQL).
I can already generate an icon with a link to appropriate file, but I can't see how I can make the record of the click on the icon to download the file also create the log record.
I am guessing I will have to use a button, and set the action of the button to run ... what? a controller action, a helper function, something else...
It is the last bit that I can't really get my head round. I would appreciate any advice from anyone who may have implemented something similar!
bw
You've got the right idea. Link to a controller action, which will write to the database & log, and will load the file and present it to the user.
Example:
class MyController extends AppController {
// Load the model
public $uses = ('DbTable');
public function get_file() {
// Save the DB record
$this->DbTable->save(...);
// Set the output header for content delivery
// (use the appropriate mime-type for your file)
header('Content-Type: image/jpg');
// Have it download as if it were an attachment
header('Content-Disposition: attachment; filename="filename.jpg"');
// Print out the file contents
echo file_get_contents('/path/to/filename.jpg');
// Prevent any further processing or rendering
exit();
}
}

Resources