GAE/J - Blobstore - how to determine if file is not uploaded - google-app-engine

I am working on web application and using GAE/J blobstore tutorial http://code.google.com/appengine/docs/java/blobstore/overview.html I was able to upload file to blobstore.
My Problem is my "upload file" option is OPTIONAL on form. So user may or maynot choose to upload the file on my form. So since this field is optional, I do not have any upfront form validation for this field, but then when i submit the form "a blank document with 0kb file gets uploaded to blobstore" since i am not able to determine if user has selected any file or not inside servlet.
I tried Apache file upload (ServletFileUpload..etc) but it keeps returning null everytime.
so not sure, how do i determine if user have selected any file to upload inside servlet?
Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(req);
if (blobs != null && blobs.size() > 0) {
BlobKey blobkey = blobs.get("myFile");
blobkeyStr = blobkey.getKeyString();
}

You can test if a blob was uploaded by checking the size of the blob. If the size is zero, you should delete the blob.
BlobstoreService bs = BlobstoreServiceFactory.getBlobstoreService();
BlobKey blobKey = bs.getUploads(req).get("blob").get(0);
final BlobInfo blobInfo = new BlobInfoFactory().loadBlobInfo(blobKey);
long size = blobInfo.getSize();
if(size > 0){
//process blob
}else{
bs.delete(blobKey);
}

In the dev environment if the user submits a form with an empty file upload, the blobkey will be null, but in production it will be non-null and the blob will be empty. So you should check for both scenarios.

FYI it may be more helpful for you to show your code.
Basically, even though your file upload is optional, you still need to send the request from the form submission through the blobstore upload url anyway. If a file was uploaded, your upload handler that gets control from GAE will be able to get a list (map) of all blobs. If no file was uploaded, that list will be empty. From there, you can process the rest of the form submission as you choose.
For the specifics of how to get that list of uploaded blobs, see this section of the documentation, but basically you're going to make this call:
Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(req);
If that map is empty, there were no blobs uploaded.

I'm assuming that you are using a form to submit directly to your upload URL? If so, you might want to add validation code on your form itself. If they've selected the form then do an async request to get an upload url to submit to. If there is no form attached then submit to a different URL that doesn't process the blob.
So for instance, when they submit, if the form is attached, submit to your servlet that generates the upload URL like this:
BlobstoreService service = BlobstoreServiceFactory
.getBlobstoreService();
String url = service
.createUploadUrl("/uploadurl");
return url;

Related

Is there any way to get content of the ZenDesk Attachments instead of redirect URL?

I need to get ZenDesk ticket attachment content like encoded format. ZenDesk API provided only the content url. By using that content url I can only able to get the redirect page of that file. But I need to automate a process that file as Base64 encoded format. Thanks in advance.
Note : I tried to migrate ZenDesk to Salesforce via Dell Boomi.
I found a resolution for my problem and I guess it's the same as yours.
In salesforce apex code I got the url response from zendesk and I used subtring method to get URL of attachment.
After that I used Pagereferece to open the URL, see below:
String exampleMyResponse= '<html><body>You are being <a href="https://xxx.zdusercontent.com/attachment/000001/sdlfkashdf98709udfah?token=eyJhbGciOiJkaX46SgYrFzTEpYqUIzpQeNnl5BMBNoRnUOsgQj389Ei7nNcGOcfGYaavlqLL2qaIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..U8oX8QnYBM1lZMb6rhQGRA.NC3Z9kHC9ZE6HhygIHHan6xWYvoPqziVx76CZ6vcNYHBuAjV-LmBclVJYumKWKXA_PDhXX27z977XKYrLJZSc85a6lJTEqd-V2mP7U6O6r0_6E9hO8CWaA1dyxYYWw8kUsgMFUaPr0wCupxm3NbDzT03ZwO6EBJj79x4UZdauiXfEUrSwdl1pPahlQE2VfFo8DprgX9GQHzRFm5lwMrhA3crogo8Ox';
**//You need to authorize your domain "https://xxx.zdusercontent.com"** in remote site
Pagereference pg = new Pagereference(exampleMyResponse.substringAfter('href="'));
**Blob b = pg.getContentAsPDF();**//Here you can use getContent() too for another type of file
//Example to save PDF
Attachment att = new Attachment(Name = 'stvm_4', Body = b, ContentType = 'application/pdf', ParentId='Sobject_Id');
insert att;

Sending attachments as an email from a form - NOT from local files

I have created a HTML email form which allows a user to enter To, subject, message, content and attachments however I cannot get the attachments to send.
I have researched online and came across many variations of this code:
messageBodyPart = new MimeBodyPart();
String filename = "/home/manisha/file.txt";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
But is there a way of sending attachments input into the form instead of adding the file path to a file in the code?
Thanks
First, the files need to be uploaded from the browser to the server using the html form. Depending on what you're using to manage the uploaded data, you can store the file data in memory or in files on the server. If you store it in memory, you can use a ByteArrayDataSource instead of FileDataSource in your code above.

MultiValueDictKeyError when Djano Imagefield is blank

I have a very simple model and form which expects user to fill in name , title etc. and also upload an image . Everything works fine but as soon as user tries to submit a record without uploading the image then it gets Multivaluedictkey error. I have set null =true and blank = true in the field definition. :"photo = models.ImageField(upload_to='media',null=True,blank=True)" . Media storage and retrieval is also working fine as long as image is uploaded by the user.In short I request your help in suggesting snything which enables me to let user submit a record without necessarily uploading an image.
Traceback:
File "/home/sampledemo/.virtualenvs/django18/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/sampledemo/mysite/polls/views.py" in someview
45. newproject.photo = request.FILES['photo']
File "/home/sampledemo/.virtualenvs/django18/local/lib/python2.7/site-packages/django/utils/datastructures.py" in __getitem__
322. raise MultiValueDictKeyError(repr(key))
Exception Type: MultiValueDictKeyError at /someview/
Exception Value: "'photo
In your code you have
newproject.photo = request.FILES['photo']
you will get MultiValueDictKeyError for the following reasons
1. request.FILES does not have the key named photo
2. request.FILES may have multiple values for the same key
If it's the 2nd case you should use request.FILES.getlist('photo') [if you upload multiple files with the same. In your case it's 'photo']

Sending images to google cloud storage using google app engine

I wrote a simple webapp using google app engine in python that allows users to upload images and have it stored somewhere (for now I'm just using the blob store based on the tutorials).
Now I want to send the images to google cloud storage, but am not sure how to do this. They provide two modes when opening a file: "a" and "r". Neither of them, to my knowledge, are for binary streams.
How can I send an image to google cloud storage? Code snippets or references would be nice.
I am planning to send small audio samples as well, and other binary data.
Also, how can I delete the image if a user wishes to delete it? There doesn't seem to be a delete method available.
Here's a simple upload handler that will write the blob that was uploaded to bigstore. Note you will need to have added your app's service account to the team account that is managing the bigstore bucket.
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file')
blob_info = upload_files[0]
in_file_name = files.blobstore.get_file_name(blob_info.key())
infile = files.open(in_file_name)
out_file_name = '/gs/mybucket/' + blob_info.filename
outfile = files.gs.create(out_file_name,
mime_type = blob_info.content_type)
f = files.open(outfile, 'a')
chunkSize = 1024 * 1024
try:
data = infile.read(chunkSize)
while data:
f.write(data)
data = infile.read(chunkSize)
finally:
infile.close()
f.close()
files.finalize(outfile)
There isn't a difference between a binary stream and a text stream in cloud storage. You just write strings (or byte strings) to the file opened in "a" mode. Follow the instructions here.
Also, if you are serving images from the blobstore, you are probably better off using get_serving_url() from here, although that depends on your application.

How can i extract attachments from salesforce?

I need to extract attatchments out of salesforce? I need to transfer some notes and attachments into another environmant. I am able to extract the notes but not sure how to go about extracting the attatchments
Thanks
Prady
This mostly depends on what tools/utilities you use to extract. The SOQL for Attachment sObject will always return one row at a time if Body field is included in the query. This is enforced to conserver resources and prevent overbearing SOQL scripts.
Approach #1, if queryMore is not available: Issue a SOQL without Body field to enumerate all attachments, then issue one SOQL per attachment ID to retrieve Body
Approach #2: Issue a SOQL to retrieve all needed attachments then loop using queryMore to get them one at a time.
Approach #3: If you can "freeze" the SF environment and just want to take snapshot of the system to pre-load a different one to be used going forward you can use "data exports". In setup menu, in data management there is an export data command, make sure you click "Include in export" to include all binary data. After due process it will give you a complete data backup you can crunch offline.
Btw, body is base64 encoded, you'll need to decode it to get the actual binary
Here is the solution I've used to get the attachment binary content from SalesForce. The example in their documentation points the following:
curl
https://na1.salesforce.com/services/data/v20.0/sobjects/Document/015D0000000NdJOIA0/body
-H "Authorization: Bearer token"
So there are a couple different elements here. The host (https://na1.salesforce.com) you should be able to get after the login process, this host is session based so it can always change. Second element is the rest of the URL, that you will get from the "body" field of the Attachment object. Third and last element is the Authorization header, which is composed by the string "Bearer ", plus the token that is given to you after you authenticate with the SF backend.
The response is the binary file, it is NOT in base64, just save it to a file and you are good to go.
Here is an example of how I did it in Objective C:
// How to get the correct host, since that is configured after the login.
NSURL * host = [[[[SFRestAPI sharedInstance] coordinator] credentials] instanceUrl];
// The field Body contains the partial URL to get the file content
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", [host absoluteString], {AttachmentObject}.body]];
// Creating the Authorization header. Important to add the "Bearer " before the token
NSString *authHeader = [NSString stringWithFormat:#"Bearer %#",[[[[SFRestAPI sharedInstance] coordinator] credentials] accessToken]];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
[urlRequest addValue:authHeader forHTTPHeaderField:#"Authorization"];
[urlRequest setHTTPMethod:#"GET"];
urlConnection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
Hope it helps.
You can use SOQl Query options, or if you are looking for some automation tool that will help you with quick export, then you can try AppExchange App Satrang Mass File Download - https://appexchange.salesforce.com/listingDetail?listingId=a0N3A00000EcsAOUAZ&tab=e
Disclaimer: I work at Satrang Technologies, the publisher of this Mass File Download AppExchange App.
In SalesForce attachment will be against an Object for e.g. Account object.
Steps to retrieve attachment (in Java)
Get the ID of the Object to which a file is attached. e.q. Account Object
String pid = Account__r().getId();
Execute a Query on Salesforce Object "Attachment" for the ID in Step 1
*String q = "Select Name, Body, ContentType from Attachment
where ParentId = '" + pid + "'";
QueryResult qr = connection.query(q);
SObject[] sarr = qr.getRecords();*
SObject so = sarr[0];
Typecast Salesforce Generic Object (SObject) to "Attachment" object
*Attachment att = (Attachment)so;*
Retrieve the Byte Array Stream from Body of Attachment, and do the operation needed on byte array.
*byte[] bName = att.getBody();
// Do your operation in byte array stream*

Resources