I try to upload my image into server converting to NSData but it's take to much time to convert images.
Can we upload image to server without converting to NSData ?
At starting I had tried sending image directly to server.
But without converting image to data and string if I tried to send it ,it could not send also it is not possible.Because in server if we send data anything to server,it must be a string format.If we send image directly,it takes much space also it should not be a data.Image must be a URL or path in server.
It depends upon the source of these images. If the images are from the photos libraries, for example, then, yes, you can retrieve the original asset, avoiding the inefficient process of converting a UIImage to a NSData (which can make the asset larger, introduce quality loss, lose metadata, etc.).
The key take home message in this scenario is not "how to avoid converting to NSData", but rather "how to avoid round-tripping the image through a UIImage and then reconverting it back to a NSData, but rather just retrieve the original asset."
But this only applies to images for which you have the original raw asset (e.g. images in the photos library, images in the documents folder, etc.). In those cases, just grab the raw NSData and you're done.
But if this is an image that you generated programmatically (e.g. a snapshot of a UIKit view), then that will have to be converted to a NSData. But if you can avoid round-tripping it through the UIImage in the first place, then you eliminate this overhead.
You can use blob data type store the data. Though its not highly recommended. You can refer these links. BLOB data type and how to use BLOB storage service as don't put large BLOBs in a database. Put them in the filesystem next to your database file and then write the filenames or an URL to the database. This will be a much faster, will use the database much more efficiently, will minimize I/O.
Related
The common method to store images in a database is to convert the image to base64 data before storing the data. This process will increase the size by 33%. Alternatively it is possible to directly store the image as a BLOB; for example:
$image = new Imagick("image.jpg");
$data = $image->getImageBlob();
$data = $mysqli->real_escape_string($data);
$mysqli->query("INSERT INTO images (data) VALUES ('$data')");
and then display the image with
<img src="data:image/jpeg;base64,' . base64_encode($data) . '" />
With the latter method, we save 1/3 storage space. Why is it more common to store images as base64 in MySQL databases?
UPDATE: There are many debates about advantages and disadvantages of storing images in databases, and most people believe it is not a practical approach. Anyway, here I assume we store image in database, and discussing the best method to do so.
I contend that images (files) are NOT usually stored in a database base64 encoded. Instead, they are stored in their raw binary form in a binary column, blob column, or file.
Base64 is only used as a transport mechanism, not for storage. For example, you can embed a base64 encoded image into an XML document or an email message.
Base64 is also stream friendly. You can encode and decode on the fly (without knowing the total size of the data).
While base64 is fine for transport, do not store your images base64 encoded.
Base64 provides no checksum or anything of any value for storage.
Base64 encoding increases the storage requirement by 33% over a raw binary format. It also increases the amount of data that must be read from persistent storage, which is still generally the largest bottleneck in computing. It's generally faster to read less bytes and encode them on the fly. Only if your system is CPU bound instead of IO bound, and you're regularly outputting the image in base64, then consider storing in base64.
Inline images (base64 encoded images embedded in HTML) are a bottleneck themselves--you're sending 33% more data over the wire, and doing it serially (the web browser has to wait on the inline images before it can finish downloading the page HTML).
On MySQL, and perhaps similar databases, for performance reasons, you might wish to store very small images in binary format in BINARY or VARBINARY columns so that they are on the same page as the primary key, as opposed to BLOB columns, which are always stored on a separate page and sometimes force the use of temporary tables.
If you still wish to store images base64 encoded, please, whatever you do, make sure you don't store base64 encoded data in a UTF8 column then index it.
Pro base64: the encoded representation you handle is a pretty safe string. It contains neither control chars nor quotes. The latter point helps against SQL injection attempts. I wouldn't expect any problem to just add the value to a "hand coded" SQL query string.
Pro BLOB: the database manager software knows what type of data it has to expect. It can optimize for that. If you'd store base64 in a TEXT field it might try to build some index or other data structure for it, which would be really nice and useful for "real" text data but pointless and a waste of time and space for image data. And it is the smaller, as in number of bytes, representation.
Just want to give one example why we decided to store image in DB not files or CDN, it is storing images of signatures.
We have tried to do so via CDN, cloud storage, files, and finally decided to store in DB and happy about the decision as it was proven us right in our subsequent events when we moved, upgraded our scripts and migrated the sites serveral times.
For my case, we wanted the signatures to be with the records that belong to the author of documents.
Storing in files format risks missing them or deleted by accident.
We store it as a blob binary format in MySQL, and later as based64 encoded image in a text field. The decision to change to based64 was due to smaller size as result for some reason, and faster loading. Blob was slowing down the page load for some reason.
In our case, this solution to store signature images in DB, (whether as blob or based64), was driven by:
Most signature images are very small.
We don't need to index the signature images stored in DB.
Index is done on the primary key.
We may have to move or switch servers, moving physical images files to different servers, may cause the images not found due to links change.
it is embarrassed to ask the author to re-sign their signatures.
it is more secured saving in the DB as compared to exposing it as files which can be downloaded if security is compromised. Storing in DB allows us better control over its access.
any future migrations, change of web design, hosting, servers, we have zero worries about reconcilating the signature file names against the physical files, it is all in the DB!
AC
I recommend looking at modern databases like NoSQL and also I agree with user1252434's post. For instance I am storing a few < 500kb PNGs as base64 on my Mongo db with binary set to true with no performance hit at all. Mongo can be used to store large files like 10MB videos and that can offer huge time saving advantages in metadata searches for those videos, see storing large objects and files in mongodb.
How can I make the way I add images to the core data more efficient?
Its a pretty bad idea to save "Data" or Image here in core data persistance. Also i think you are running this code in the background queue, if not then thats also a bad thing. But then again, saving the image or data into core data persistant store is a very bad idea and should be avoided whenever you can.
As an alternate you can do this -
Save the image in the local directory with a path and a unique
filename.
Save the filename in core data except the path.
Next time when you retrieve the image, get the filename from the Data store.
Append the filename with the whole path untill the folder. Retrieve the image.
This is a much more efficient and better way to store images.
I'm writing an app to consume REST Api which provide JSON response. I'm using CoreData to store object from JSON to support offline feature. Object has some image attributes (Which is image url from JSON response).
My question is should I store image attributes as Data (Using binary data) to CoreData (can check use external storage from CoreDataXCModel) or should I need to only store the image path (As String) and use some library such as Kingfisher, AlamofireImage, SDWebImage to load image from image url stored in Coredata? which one is better design?
1 more thing is for how we handle big image? Can we generate 1 thumbnail which is specific size and 1 full image size.
I suggest you to store URL in database and use some framework like SDWebImage to load. These frameworks have caching mechanism so that once an image is loaded it gets cached.
You could preferably get a thumbnail image as a link in the JSON response too.
Save the urlString, I think, in most cases the urlStrting is a better solution, because in the era of 3 g / 4 g mobile phone App has greater amounts of image data, the local store they are a very difficult thing, unless you have a 1024 TB of the iPhone.
And you should provide an interface, like long press to push an view(Or anything) to tell user they can save the image to local.
Don't forget load local image at first and provide an interface tell user they can remove the local data.
I want to develop the solution where storing of image data downloaded from server and display it.
Scenario is, There will be thumbnail images placed on each row, clicking on that will download the actual image from server and display the image in a bigger view.
I want to store this image data once its downloaded from server, so that in the later stage if the same thumbnail has clicked to open, I don't need to again download the actual image from server, instead I can pull that from the place where I stored locally.
There will be more than 80 thumbnail images placed in rows and corresponding bigger images on the server.
Can I store the image data in a file and store it in documents directory or some thing like that? My worry, if the user selected all the 80 thumbnail images, then i'll have to store all the 80 bigger images locally on the app.
What is the best way to achieve this storing solution? Please advise.
Thank you.
You can store the images in the documents folder, as you already said. Just make sure to exclude them from backups, Apple will reject you for storing too much replaceable data in there.
There are also some third party image cache libraries, most notably (afaik) FastImageCache from Path:
https://github.com/path/FastImageCache
From their website what FastImageCache does is this:
Stores images of similar sizes and styles together
Persists image data to disk
Returns images to the user significantly faster than traditional methods
Automatically manages cache expiry based on recency of usage
Utilizes a model-based approach for storing and retrieving images
Allows images to be processed on a per-model basis before being stored into the cache
I have been developing an app with cloud/server data source. So naturally the process is one thing at a time. So at present, to fill my tables, I query the server which returns an array. The array contains urls to images and then from the urls I load the images using SDWebImage.
Now I am entering the stage of development where I need to implement Core Data for all the data in my tables (i.e. texts and images). So far I am considering the following approaches:
I can load the array from the server into core data (imagine properties as: firstName, lastName, photoUrl, shortBio) and then pass the photo url from core data to SDWebImage to display the image in the table cells. OR
I can load the array and the image into Core Data (i.e. load the array into core data in the background and then for each row, load the image into core data)
Of course the point here is that if I use SDWebImage it will save the image in its own caching system, which from my limited understanding may or may not be entirely consistent with what is in core data. On the other hand I don't understand core data enough to know if it handles saving images well in terms of performance (i.e. knows it's an image and therefore handle the file linking).
So What is the best way to do this? Can SDWebImage work in harmony with Core Data? Or is SDWebImage redundant since core data is good enough all by itself?
Another thing to note is that presently, my data loads from server immediately and then the images come as SDWebImage loads each into its UIImageView. This may not be a problem with Core Data since ideally the image will be in the local DB. Any thoughts?
Based on your question and comments, it seems you are trying to locally cache images that were retrieved through an HTTP request.
The URL loading system is already caching the images. There is no need to implement another layer of caching on top of that, wether it be SDWebImage or CoreData. When an HTTP response is received from the server, the server includes "freshness" information that informs the client how long and under what conditions that response is valid. The URL loading system, by default, obeys those rules. You can check the freshness information of responses using a tool like Charles or REDBot. The server is the only party in this conversation that can know how long a response is valid for.
The URL loading system does not, by default, cache to the filesytem - only in-memory. This is easy to change:
cache = [[NSURLCache alloc] initWithMemoryCapacity:(1024*1024*512) diskCapacity:(1024*1024*1024 * 100) diskPath:#"Cache.db"];
[NSURLCache setSharedURLCache:cache];
Or when using NSURLSession:
cache = [[NSURLCache alloc] initWithMemoryCapacity:(1024*1024*512) diskCapacity:(1024*1024*1024 * 100) diskPath:#"Cache.db"];
[sessionConfiguration setURLCache:cache];
session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
Storing image data in Core Data is something in general to be avoided, at least with the NSSQLiteStoreType persistent store. Even small images are large in the SQLite database and cause fragmentation, etc. that impact performance. If you are going to store image data in Core Data, it's preferable to use external storage - either by use Core Data's own external records storage, or by storing image data on the filesystem and referencing it in managed objects by using URLs.
However, if you are using Core Data OR SDWebImage to "cache" images, you are ignoring the freshness information that was returned in the server's response unless you implement your own validation layer - which the URL loading system is already doing for you!
Regardless of the question semantics, I think you need some more hard information to inform your decision.
It would be useful for you to know that storing large images (larger than, say, thumbnails) is not recommended and will lead to performance issues. Core Data has an option for large data where you can check "Store in External Record File". Alternatively, you can administer your own cache data (in this way you can flexibly update the images via download on a per-need basis on each device sharing the same data). The accepted best practice is to only store the image URL in Core Data (typically relative to the application directory) and handle the file storage / display separately.
I do not know SDWebImage, but this might provide some of the functionality that you need in the light of the above.
I hope this helps you make your decision about the data architecture.