How to upload multiple pictures to Volusion through API - ruby-on-rails

This is my Volusion item insert method, which relies on the HTTParty gem for rails. It works for posting items without photos, and posting items with a single photos by using the <PhotoURL_Large> and <PhotoURL_Small> XML tags.
def self.post_volusion_item(hide_product, product_code, product_name, product_description, availability, custom_field1, custom_field2, enable_options_inv_control, free_shipping_item, height, length, width, metatag_description, metatag_title, photo_alt_text, photo_xml, product_category, product_price, product_weight, metatag_keywords)
encrypted_password = ENV['VOLUSION_PASSWORD']
post_url = "https://WEBSITE-HERE/net/WebService.aspx?Login=LOGIN-HERE&EncryptedPassword=#{encrypted_password}&Import=Insert"
body = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Volusion_API><Products><HideProduct>#{hide_product}</HideProduct><ProductCode>#{product_code}</ProductCode><ProductName>#{product_name}</ProductName><ProductDescription>#{product_description}</ProductDescription><Availability>#{availability}</Availability><CustomField1>#{custom_field1}</CustomField1><CustomField2>#{custom_field2}</CustomField2><EnableOptions_InventoryControl>#{enable_options_inv_control}</EnableOptions_InventoryControl><FreeShippingItem>#{free_shipping_item}</FreeShippingItem><Height>#{height}</Height><Length>#{length}</Length><Width>#{width}</Width><METATAG_Description>#{metatag_description}</METATAG_Description><METATAG_Title>#{metatag_title}</METATAG_Title><Photo_AltText>#{photo_alt_text}</Photo_AltText><PhotoURL_Large>#{photo_url_large}</PhotoURL_Large><PhotoURL_Small>#{photo_url_small}</PhotoURL_Small><ProductCategory>#{product_category}</ProductCategory><ProductPrice>#{product_price}</ProductPrice><ProductWeight>#{product_weight}</ProductWeight><METATAG_Keywords>#{metatag_keywords}</METATAG_Keywords></Products></Volusion_API>"
post(post_url, body: body)
end
I can not find any documentation that gives an example with multiple photos in the item. I have tried duplicating the calls. Example: <PhotoURL_Large>img1</PhotoURL_Large><PhotoURL_Small>img1</PhotoURL_Small><PhotoURL_Large>img2</PhotoURL_Large><PhotoURL_Small>img2</PhotoURL_Small>
This resulted in no images uploading.
I am realizing the the PhotoURL is not related to the urls of the item's photos, but only tied to the data in Volusion's add item form.
Can someone point me in the right direction for accessing the true photo urls for volusion items?

In Volusion, PhotoURL_Small and PhotoURL_Large are alternate image URLs that can either point to an internal or external location. Volusion only provides one of each for each product code which will be used by the product in place of any loaded image. So if you populate any of the above two fields for that product it will use that URL in place of any image uploaded via the image manager or any images directly uploaded via FTP. There is no provision in the software for additional PhotoURL_Small and PhotoURL_Large images.
Here is an excellent explanation of image file structure.
Image structure

Related

How can I preserve storage space and load time with Active Storage?

I have a user submission form that includes images. Originally I was using Carrierwave, but with that the image is sent to my server for processing first before being saved to Google Cloud Services, and if the image/s is/are too large, the request times out and the user just gets a server error.
So what I need is a way to upload directly to GCS. Active Storage seemed like the perfect solution, but I'm getting really confused about how hard compression seems to be.
An ideal solution would be to resize the image automatically upon upload, but there doesn't seem to be a way to do that.
A next-best solution would be to create a resized variant upon upload using something like #record.images.first.variant(resize_to_limit [xxx,xxx]) #using image_processing gem, but the docs seem to imply that a variant can only be created upon page load, which would obviously be extremely detrimental to load time, especially if there are many images. More evidence for this is that when I create a variant, it's not in my GCS bucket, so it clearly only exists in my server's memory. If I try
#record.images.first.variant(resize_to_limit [xxx,xxx]).service_url
I get a url back, but it's invalid. I get a failed image when I try to display the image on my site, and when I visit the url, I get these errors from GCS:
The specified key does not exist.
No such object.
so apparently I can't create a permanent url.
A third best solution would be to write a Google Cloud Function that automatically resizes the images inside Google Cloud, but reading through the docs, it appears that I would have to create a new resized file with a new url, and I'm not sure how I could replace the original url with the new one in my database.
To summarize, what I'd like to accomplish is to allow direct upload to GCS, but control the size of the files before they are downloaded by the user. My problems with Active Storage are that (1) I can't control the size of the files on my GCS bucket, leading to arbitrary storage costs, and (2) I apparently have to choose between users having to download arbitrarily large files, or having to process images while their page loads, both of which will be very expensive in server costs and load time.
It seems extremely strange that Active Storage would be set up this way and I can't help but think I'm missing something. Does anyone know of a way to solve either problem?
Here's what I did to fix this:
1- I upload the attachment that the user added directly to my service provider ( I use S3 ).
2- I add an after_commit job that calls a Sidekiq worker to generate the thumbs
3- My sidekiq worker ( AttachmentWorker ) calls my model's generate_thumbs method
4- generate_thumbs will loop through the different sizes that I want to generate for this file
Now, here's the tricky part:
def generate_thumbs
[
{ resize: '300x300^', extent: '300x300', gravity: :center },
{ resize: '600>' }
].each do |size|
self.file_url(size, true)
end
end
def file_url(size, process = false)
value = self.file # where file is my has_one_attached
if size.nil?
url = value
else
url = value.variant(size)
if process
url = url.processed
end
end
return url.service_url
end
In the file_url method, we will only call .processed if we pass process = true. I've experimented a lot with this method to have the best possible performance outcome out of it.
The .processed will check with your bucket if the file exists or not, and if not, it will generate your new file and upload it.
Also, here's another question that I have previously asked concerning ActiveStorage that can also help you: ActiveStorage & S3: Make files public
I absolutely don't know Active Storage. However, a good pattern for your use case is to resize the image when it come in. For this
Let the user store the image in Bucket1
When the file is created in Bucket1, an event is triggered. Plug a function on this event
The Cloud Functions resizes the image and store it into Bucket2
You can delete the image in Bucket1 at the end of the Cloud Function, or keep it few days or move it to cheaper storage (to keep the original image in case of issue). For this last 2 actions, you can use Life Cycle to delete of change the storage class of files.
Note: You can use the same Bucket (instead of Bucket1 and Bucket2), but an event to resize the image will be sent every time that a file is create in the bucket. You can use PubSub as middleware and add filter on it to trigger your function only with the file is created in the correct folder. I wrote an article on this

photoswipe: pid/gid link to particular photo

I wonder how photoswipe builds URL to a particular image in a gallery?
I see that for each image in a gallery the following URL is built: [BASE_URL]#&gid=2&pid=3. If I get it right, the pid/gid values are taken in the order of gallery/photo appearance on a page. Which presents problem for dynamic content when galleries/photos are shuffled (sorted, deleted, etc.)
Is there a way to overrule that logic such that static ID's (e.g. database PK's) are used?
Thank you.
After digging into the sources I found out that if gallery element has attribute data-pswp-uid= set to some value, then that value is used in URL as gid.
Unfortunately, same trick on an image/figure didn't do.

YouTube videos in Orchard CMS

I have a medialibrarypickerfield, I've added a youtube video to it.
How can I get access to the YouTube video URL in an alternate at the following level:
MediaLibraryPicker-ContentType-VideoFieldName.cshtml
I've tried
var field = (MediaLibraryPickerField) Model.ContentField;
var contents = field.MediaParts;
to gain access to each MediaPart/video but when I iterate through the MediaParts, the MediaUrl is null. I know this has something to do with the OEmbedPart but I don't know how to access this.
Extremely frustrating so far. An otherwise very simple task outside of Orchard to store and retrieve URLs.
To access the oEmbed part, just do As<OEmbedPart>() on the media part. You can then access the URL for the video by using the Source property of the part. You can also access a number of properties that are provided by the oEmbed site (YouTube in your case). Those properties can be accessed using the indexer on the part.
For example, part["html"] will give you the html code to embed in your page to render the video player:
#Html.Raw(part["html"])
There is also a "thumbnail" or a "thumbnail_url" property (depending on provider) that will give you the url of a thumbnail image. You can look at the whole blob of XML underlying that in the Framework_ContentItemRecord table's Data column. There is also a width and a height for example.

How to get bigger size pictures if me/home items in facebook sdk

Now i'm using Facebook SDK on my ASP.NET MVC5 project, and for data query I use Graph Api.
When I read a data from "me/home", almost each read item of it have key called "picture", that represents image attached to post. But it is thumnbail size, how can I get it bigger resolution and better quality?
Link i got look smth like this:
https://fbcdn-sphotos-e-a.akamaihd.net/hphotos-ak-xpa1/v/t1.0-9/s130x130/1902827_682459971849744_3936731463452030828_n.jpg?oh=a31397c18fc806dcd1b60565009fd50b&oe=54BAA327&gda=1420888048_5c40d0ab0d0b0f5636d7965138f7f6ab
I hope for your help.
Thank you for your time
There is a variable in the API "type" using that you can specify the sizes of the image
The type parameter can be one of square, small, normal, or large for profile pictures or thumbnail, normal, album for album pictures.
image src would be something like this
https://graph.facebook.com/xxx/picture?access_token=yyy&type=normal
you can find more information # http://developers.facebook.com/docs/reference/api/user/
string imageUrl = fb.Get("/me?fields=picture.type(large)").ToString();

mvc file upload and database insert

I'm just getting my head wrapped around MVC in .net using VS 2013.
I need a little direction in regards to uploading a file (which is easy) but also inserting data about that image into a database. Specifically I want to allow the end user to enter a description, title etc. about the file being uploaded. On the back-end I want to also add to the meta data a 'Date Created', 'Path to the file', 'Category', and the File Name and a couple other pieces of data that will help with presenting files in the views. I don't want to insert the files in the DB but just use the path in the generated HTML to point to the physical file so the end user can view or download it.
Multiple file types are being used, Audio, Video, Documents, Images.
I can get the file upload to work but writing the controller to accept a file, and end user input, then also add the other fields I need into the database that the user never sees is where I'm stuck. Blending the file upload with the user fields and beack end data is confusing me on how to get all the pieces to work together.
So in short getting File Upload + User Input + non-User Input values all in the same View, Controller, and Model is what I need direction on.
You have to upload your image plus data in a multi-part form.
In your view you will create a POST form that uses "multipart/form-data" encoding, you can then include inputs for model data and your file upload control within the body of the form. When it submits will will create a multi-part form, one part will contain the binary file and another part will contain your data.
On the controller action side you will receive the data with an action akin to
public ActionResult PostFile(MyModel model, HttpPostedFileBase file) {...}
There are numerous posts on SO with more details so I won't go into that.

Resources