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.
Related
When I call the captions.download endpoint with an ID that we retrieve from the captions.list endpoint, it always returns a 403. For example:
https://www.youtube.com/watch?v=1HRwpwOj4aA
I call captions.list with:
GET https://www.googleapis.com/youtube/v3/captions?part=id&videoId=1HRwpwOj4aA&key={YOUR_API_KEY}
This is response:
cache-control: private, max-age=0, must-revalidate, no-transform
content-encoding: gzip
content-length: 236
content-type: application/json; charset=UTF-8
date: Sat, 23 May 2015 17:55:57 GMT
etag: "dhbhlDw5j8dK10GxeV_UG6RSReM/Rztb3ln4Zb6O07vb7_KSZi2y1NM"
expires: Sat, 23 May 2015 17:55:57 GMT
server: GSE
vary: Origin, X-Origin
{
"kind": "youtube#captionListResponse",
"etag": "\"dhbhlDw5j8dK10GxeV_UG6RSReM/Rztb3ln4Zb6O07vb7_KSZi2y1NM\"",
"items": [
{
"kind": "youtube#caption",
"etag": "\"dhbhlDw5j8dK10GxeV_UG6RSReM/pwH-4wtyQJz0U3l57fA8uKm4e1I\"",
"id": "kHlUsiuNS4TjB25loauZNXGrjK91I1tEdNyOpTRNA78="
}
]
}
When I use the above id to call captions.download:
GET https://www.googleapis.com/youtube/v3/captions/kHlUsiuNS4TjB25loauZNXGrjK91I1tEdNyOpTRNA78%3D?key={YOUR_API_KEY}
This is response:
403 Forbidden
cache-control: private, max-age=0
content-encoding: gzip
content-length: 29
content-type: text/html; charset=UTF-8
date: Sat, 23 May 2015 17:59:05 GMT
expires: Sat, 23 May 2015 17:59:05 GMT
server: GSE
vary: Origin, X-Origin
Forbidden
Any ideas what could be happening here?
From the YouTube API docs:
403 Forbidden: The permissions associated with the request are not
sufficient to download the caption track. The request might not be
properly authorized, or the video order might not have enabled
third-party contributions for this caption.
Instead caption download API that sometimes returns 403 (if video not have enabled third-party contributions for this caption) you can use youtube.com/api/timedtext
what you wrote above about "only works for videos your google account owns" is not my experience. I just successfully ran captions.download on a video (about dog training) which I definitely do not own - do not even have a dog. However, I have tested the exact same code on the video mentioned here on stackoverflow and get a 403 error.
So no it doesn't always return a 403 sometimes it returns a 200! Try it with the dog video mentioned above:
python captions.py --videoid="jBN2_YuTclU" --action="download" --captionid='8S2GjnNfitU5HHoLyTeLxq_W1dP29YRFC8E8vFBUtws='
with the code you probably already have here.
It will need your client_secrets.json downloaded from the Google credentials page somewhere and a missing file youtube-v3-api-captions.json which you can get from here. The code launches a browser where you log in for OAuth2 authorisation.
Still, there must be a reason why it works for some videos and not others. #Abhishek might have it above. The wrong comment has been upvoted there. Nothing in the output of captions.list for a video that allows captions downloads and a video that does not is obviously different which would explains why one works and the other does not. If anyone can supply which {'key':'value'} pair in the youtube api controls this would be helpful.
Status 403 Forbidden means that nobody has the right to access that URL. You shouldn't receive that message if you have the wrong API key, for example; that should give Status 401 Unauthorised. I'd check the URL carefully.
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.
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.
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.
I'm new to Nimbus. Right now my app is trying to retrieve 4 images via this code:
for (int i=minFoto; i<=maxFoto; i++) {
NINetworkImageView* networkImageView = [self networkImageView];
NSString *resourceURL = [NSString stringWithFormat:#"%#registration/rest/users/account_get_foto/%#?fotoId=%d", baseURL, ssid, i];
NSLog(resourceURL);
[networkImageView setPathToNetworkImage:resourceURL
forDisplaySize: CGSizeMake(50, 50)
contentMode: networkImageView.contentMode];
I know my loop is working because I see all four NSLog's come out correctly. However, I am only getting the first image. networkImageViewDidStartLoad is only being called once and neither didLoadImage or networkImageViewDidFailLoad is being called. I think it is odd that didLoadImage is never being call. Never. I know I have the data because I'm using CharlieProxy (great app BTW, well worth the $50) and it shows the image data in the response packets.
So I commented this out of my delegate:
[[Nimbus networkOperationQueue] setMaxConcurrentOperationCount:1];
And as you might expect, I'm getting 4 calls to networkImageViewDidStartLoad, and still zero to didLoadImage or networkImageViewDidFailLoad.
Here are my request headers (from CharlieProxy)
GET /registration/rest/users/account_get_foto/fdbc2222-7b75-4ff4-b111-623e951e5b00?fotoId=134 HTTP/1.1
Host: -------------:8080
User-Agent: Ferret/1.0 CFNetwork/548.0.3 Darwin/11.2.0
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive
and here's the response headers, showing a "200 OK"
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet/3.0; JBossAS-6
Content-Type: image/*
Content-Length: 461109
Date: Tue, 31 Jan 2012 21:12:33 GMT
âPNG (png data deleted...)
I'm a little puzzled now. My server is clearly returning the image data, but my app just isn't getting it. Any ideas?
Well, I found it. Might as well put the answer in for future googlers.
My networkImageView had gone out of scope and was ARC'd. Funny, I thought I had saved it away, but that code was partially commented out!