So I'm using SDWebImage to load images asynchronously in my iOS UITableView. To do this I call:
[cell.itemImageView setImageWithURL:imageUrl placeholderImage:[UIImage imageName:#"placeholder.png"]];
Where imageUrl might be:
imageUrl = [NSURL URLWithString:#"http://example.org/image.png"];
This all works fine, however the server API I'm using will occasionally return an image without an image extension. In this case SDWebImage appears to not attempt to load the image. Is there anyway I can force it to download the image? I cannot just append .png to the image as this causes permissions issues where the image is hosted.
EDIT: I have just ran this on a example image currently hosted (the GUID is the filename):
curl -i -X HEAD http://example.org/images/98b67f6a-671c-482c-8e3b-0ade8bfa01be
And it returns with this:
HTTP/1.1 200 OK
x-amz-id-2: UGcGcyUuUfWBD2YrhmfoRq8oiXIwEkBJ9x4TdimLAcPc9Yim26tRRgjN/PVBak+S
x-amz-request-id: 513EDF3EB400DE6E
Date: Mon, 12 Aug 2013 16:03:08 GMT
Last-Modified: Thu, 13 Jun 2013 01:28:50 GMT
ETag: "96ca8a122a94c97eee83ef685c7e2e7b"
Accept-Ranges: bytes
Content-Type: image/jpg
Content-Length: 17631
Server: AmazonS3
Not really an answer but to resolve this I ended up changing the server to save images with their extension.
The content type returned by the server is currently image/jpg; it should be image/jpeg instead.
Related
I'm using AlamofireImage for loading images into an ImageView in a tableview cell (in a separated xib file)
The problem is that the image never shows up. I think the code is right and url is valid too.
Here is the code (very simple):
let placeholderImage = UIImage(named: "imgNoPhoto1")
if let urlImage = NSURL(string: urlString) {
photoImage.af_setImageWithURL(urlImage, placeholderImage: placeholderImage)
}
Any ideas? Could be that the cell is not being reloaded? I have tested it in iOS 8 and 9.
Hope you help me!
Thank you
Depending on whether you're cancelling the request in prepareForReuse or not, you may be running into a bug that I just fixed in AlamofireImage #55. I'll be pushing out a new release with this fix here in the next couple of days. If this is actually what you're running into, you could comment out the cancellation logic for now and that should fix your problem until we release the fix.
If this is not the issue you are running into, then I'd follow the advice of everyone else and make sure you can download the image using cURL.
Update #1
Okay, I found out what your issue is. The server is not returning a valid content type which is causing AlamofireImage to not validate the image and it won't try to decode the data into an image. You can find this by running the following command in Terminal:
curl -H "User-Agent: iOS" -s -D - http://files.encuentra24.com/normalsq/sv/58/08/68/sv/58/08/68/5808689_5e7d99.jpg -o /dev/null
What this does is run curl against the URL you provided. It doesn't download the image data, it just prints out the response headers. I also found that you need to pass the User-Agent header, otherwise you'll always get a 403. Here's what the curl command will print out:
cnoon:~$ curl -H "User-Agent: iOS Example/com.alamofire.iOS-Example (1; OS Version 9.1 (Build 13B137))" -s -D - http://files.encuentra24.com/normalsq/sv/58/08/68/sv/58/08/68/5808689_5e7d99.jpg -o /dev/null
HTTP/1.1 200 OK
Cache-Control: max-age=2592000, public
Content-Type: image/jpg
Date: Fri, 11 Dec 2015 16:16:38 GMT
Expires: Sun, 10 Jan 2016 16:16:38 GMT
Pragma: no-cache
Server: nginx/1.7.12
Set-Cookie: sessioninfo=uv491lgtjqvkmt267l1nmlbm24; path=/
Set-Cookie: esid=deleted; expires=Thu, 11-Dec-2014 16:16:37 GMT; path=/
Vary: Accept-Encoding
Content-Length: 23757
Now the REALLY important part of this output is the Content-Type: image/jpg. That's not actually a valid Content-Type header. The valid one is image/jpeg. Therefore, AlamofireImage by default won't validate this response and won't decode the image.
Solution
Thankfully, we already have support for this built into AlamofireImage. You can add a custom content-type to the Request response serializers. How you do that is as follows:
Alamofire.Request.addAcceptableImageContentTypes(["image/jpg"])
This will register the image/jpg content type as an acceptable content type with the response serialization system. After registering, any content type matching image/jpg will be decoded. For more info about this, please refer to AlamofireImage #58.
I just found a partial response being cached as complete in one of our customer's machines, which rendered the whole website unusable. And I have absolutely no idea, what could possible have gone wrong there.
So what could have possibly gone wrong in the following setup?
On the server-side, we have an ASP.NET-application running. One IHttpHandler handles requests to javascript-files. It basically minifies the files as they are requested and writes the result on the response-stream. It does also log the length of the string being written to the Response-Stream:
String javascript = /* Javascript is retrieved here */;
HttpResponse response = context.Response;
response.ContentEncoding = Encoding.UTF8;
response.ContentType = "application/javascript";
HttpCachePolicy cache = response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.SetMaxAge(TimeSpan.FromDays(300));
cache.SetETag(ETag);
cache.SetExpires(DateTime.Now.AddDays(300));
cache.SetLastModified(LastModified);
cache.SetRevalidation(HttpCacheRevalidation.None);
response.Headers.Add("Vary", "Accept-Encoding");
Log.Info("{0} characters sent", javascript.length);
response.Write(javascript);
response.Flush();
response.End();
The content is then normally sent using gzip-encoding with chunked transfer-encoding. Seems simple enough to me.
Unfortunately, I just had a remote-session with a user, where only about 1/3 of the file was in the cache, which broke the file of course (15k instead of 44k). In the cache, the content-encoding was also set to gzip, all communication took place via https.
After having opened the source-file on the user's machine, I just hit Ctrl-F5 and the full content was displayed immediately.
What could have possibly gone wrong?
In case it matters, please find the cache-entry from Firefox below:
Cache entry information
key: <resource-url>
fetch count: 49
last fetched: 2015-04-28 15:31:35
last modified: 2015-04-27 15:29:13
expires: 2016-02-09 14:27:05
Data size: 15998 B
Security: This is a secure document.
security-info: (...)
request-method: GET
request-Accept-Encoding: gzip, deflate
response-head: HTTP/1.1 200 OK
Cache-Control: public, max-age=25920000
Content-Type: application/javascript; charset=utf-8
Content-Encoding: gzip
Expires: Tue, 09 Feb 2016 14:27:12 GMT
Last-Modified: Tue, 02 Jan 2001 11:00:00 GMT
Etag: W/"0"
Vary: Accept-Encoding
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Date: Wed, 15 Apr 2015 13:27:12 GMT
necko:classified: 1
Your clients browser is most likely caching the JavaScript files which would mean the src of your scripts isn't changing.
For instance if you were to request myScripts
<script src="/myScripts.js">
Then the first time, the client would request that file and any further times the browser would read its cache.
You need to append some sort of unique value such as a timestamp to the end of your scripts so even if the browser caches the file, the new timestamp will act like a new file name.
The client receives the new scripts after pressing Ctrl+F5 because this is a shortcut to empty the browsers cache.
MVC has a really nice way of doing this which involves appending a unique code which changes everytime the application or it's app pool is restarted. Check out MVC Bundling and Minification.
Hope this helps!
I have an ID of a Youtube video and like to add a Thumbnail with the google-api-client (Ruby). My request looks like this
result = client.execute(:api_method => youtube.thumbnails.set, :parameters => { :videoId => my_video_id, :media_body => file })
What result.data returns is this
<Google::APIClient::Schema::Youtube::V3::ThumbnailSetResponse:0x86435518 DATA:{"error"=>{"code"=>500, "message"=>nil}}>
I can't figure out, what the problem is here. I tried to use a path to a file on my local machine as well as a URL. Even an empty String as the file location or leaving out the media_body leads to the 500 error.
Does anyone of you know, what's going on here and why I don't get a clear error response?
Edit: It seems to be not the fault of the google-api-client, because testing the same request in the Google APIs Explorer produces the same result:
Response
500 Internal Server Error
cache-control: private, max-age=0
content-encoding: gzip
content-length: 66
content-type: application/json; charset=UTF-8
date: Wed, 19 Feb 2014 14:24:23 GMT
expires: Wed, 19 Feb 2014 14:24:23 GMT
server: GSE
{
"error": {
"code": 500,
"message": null
}
}
Not all channels are enabled for custom thumbnails; I suspect that if you're getting an error, it might be because you're attempting to set a custom thumbnail for a video in a channel that isn't enabled. There's more info at https://support.google.com/youtube/answer/72431?hl=en
Could you follow the steps in that help article and see whether you have an option in the web UI to set a custom thumbnail? If you don't, then your channel isn't enabled.
Getting back a HTTP 500 response is obviously unhelpful, though, and makes it difficult to confirm that that's what's going on. We can follow up with the engineering team about that to get a helpful error returned once we confirm whether your channel is enabled or not.
I have a problem I'm trying to use the component idhttp using indy in delphi 2010, the problem is I'm trying to get the following information when using idHTTP1.Head ():
HTTP/1.1 200 OK
Date: Mon, 16 Jun 2003 2:53:29 GMT
Server: Apache/1.3.3 (Unix) (Red Hat / Linux)
Last-Modified: Wed, October 7, 1998 11:18:14 GMT
ETag: "1813-49b-361b4df6"
Accept-Ranges: bytes
Content-Length: 1179
Connection: close
Content-Type: text / html
The problem is not that I have to do to get this information because I can not get with idHTTP1.Request.RawHeaders.Values, someone could say that I have to do.
You are looking in the wrong place. You need to look in IdHTTP1.**Response**.RawHeaders instead. Also, all of those values actually have individual properties associated with them, eg:
IdHTTP1.Response.ResponseVersion
IdHTTP1.Response.ResponseCode
IdHTTP1.Response.ResponseText
IdHTTP1.Response.Date
IdHTTP1.Response.Server
IdHTTP1.Response.LastModified
IdHTTP1.Response.ETag
IdHTTP1.Response.AcceptRanges
IdHTTP1.Response.ContentLength (also IdHTTP1.Response.HasContentLength)
IdHTTP1.Response.Connection
IdHTTP1.Response.ContentType
There is a method in AFNetworking that can set image conveniently:
- (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage
but if the url image have no extension(like http://static.qyer.com/album/user/330/21/QkpVQBsHaA/670), there are some problems,sometimes the image can be displayed exactly some times it is not displayed.
I found a method
[AFImageRequestOperation addAcceptableContentTypes:<#(NSSet *)contentTypes#>];
how should I set the contentTypes?
If you curl the URL provided, you can see the problem:
curl -i -X HEAD http://static.qyer.com/album/user/330/21/QkpVQBsHaA/670
HTTP/1.0 200 OK
Server: nginx/1.0.11
Date: Fri, 29 Mar 2013 02:03:24 GMT
Content-Type: application/octer-stream
Last-Modified: Tue, 19 Mar 2013 09:40:23 GMT
ETag: "53430075-9814c-4d843e4fc6fc0"
Accept-Ranges: bytes
Content-Length: 622924
Powered-By-ChinaCache: MISS from 060531Q354
Powered-By-ChinaCache: MISS from 060532235y
Connection: close
Content-Type: application/octer-stream (which is, strangely, a misspelling of application/octet-stream), is not a valid image mime type. If you have any control over the server, I would strongly recommend you fix this to send real mime types—for the sake of everyone accessing the CDN.
Otherwise, I would recommend you add */* to the list of acceptable content types. This should accept anything thrown at it. You can also manually specify any content types you might expect the CDN to serve, including application/octer-stream.