function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
henryCHhenryCH 

Problem loading image file via HTTP Request

Hi,

 

I'd like to use HTTP classes to load an image from the web then save it as an Attachment and finally send it attached to an email. At first glance everything seems to work fine. But the picture I receive is obviously a corrupt file. Any ideas what's wrong with my code:

 

 

public class EmailTestCtr {
	
	public Integer totalFileSize {get; set;}
	public Email__c mail {get; set;}
	public String contentType {get; set;}
	public String response {get; set;}
	
	public EmailTestCtr(){
		totalFileSize = 0;
	}
	
	public void loadFile(){
		String url = '';
		
		Http h = new Http();
		HTTPRequest req = new HttpRequest();
        
        req.setEndpoint('http://www.clienthouse.com/images/f106e78f34/CH_location_web1.jpg');
        req.setMethod('GET');
        req.setCompressed(false);
		
		HTTPResponse resp = h.send(req);
		this.contentType = resp.getHeader('Content-Type');
		this.response = resp.getHeader('Content-Length');
		
		System.debug(resp.getBody());
		String body = resp.getBody();
		
		Attachment a = new Attachment();
		try {		
			if(this.mail == null){
				mail = new Email__c(
					Name = 'test'
				);
				insert mail;
			}
			
			a.Body = Blob.valueOf(body);
			a.Name = 'Name';
			a.ParentId = mail.Id;
			a.ContentType = this.contentType;
			insert a;
		} catch(DMLException e){
			ApexPages.addMessages(e);
		}
		
		this.totalFileSize += [select BodyLength from Attachment where Id = :a.Id].BodyLength;
		
	}
	
	public void sendEmail(){
		
		Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
		String[] toAddresses = new String[] {'h.hess@clienthouse.com'};
		email.setToAddresses(toAddresses);
		email.setSubject(this.mail.Name);
		email.setPlainTextBody('Text goes here.');
		List<Messaging.EmailFileAttachment> files = new List<Messaging.EmailFileAttachment>();
		for(Attachment file : [select Name, Body, ContentType from Attachment where ParentId = :this.mail.Id]){
			System.debug('------------>FILE' + file);
			Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
			efa.setBody(file.Body);
			efa.setContentType(file.ContentType);
			efa.setFileName(file.Name + '.jpg');
			files.add(efa);
		}
		email.setFileAttachments(files);
		
		Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
		
	}
	
}

 

 

Thanks and best regards,

Henry

Best Answer chosen by Admin (Salesforce Developers) 
TerryLuschenTerryLuschen

I found a link that knows how to do this...

http://stackoverflow.com/questions/9632570/upload-image-from-android-client-to-salesforce-custom-object

 

In the recent Spring release (v24) ... you can now work with binary data (blobs in apex) directly in the http request or response. Here's an example of making a HTTP GET request for an image PNG file, and saving it to the document object in salesforce.

 

Here is the code in that link:

 

HttpRequest r = new HttpRequest();
r.setMethod('GET');
r.setEndpoint('http://www.pocketsoap.com/osx/soqlx/soqlxicon.png');
Http http = new Http();
HttpResponse res = http.send(r);
blob image = res.getBodyAsBlob();

Document d = new Document();
d.name = 'logo.png';
d.body = image;
d.folderId = UserInfo.getUserId();
insert d;
system.debug(d.id);

All Answers

joshbirkjoshbirk

I don't think it's your code.  I think because HTTPResponse stores body as a string, you'll need to be able to access the image originally as Base64Encoded, so it won't get corrupted in the process.  Then you can decode into a blob.

henryCHhenryCH

Hi Josh,

 

Thanks for your reponse. Does that really mean that Apex cannot handle binary data via HTTP because everything is converted into unencoded strings?? Sounds unbelievable to me. Is there nobody out there who tried this before??

 

Thanks and best regards,

Henry

henryCHhenryCH

Some final remarks.

 

This is a critical limitation for us so I tried to find a workaround for this problem. Browsing the docs I stumbled over the PageReference object's getContent() method. Compared to HTTPResponse.getBody() this method returns a Blob, so I tested something like:

 

 

Blob b = new ApexPages.PageReference('http://www.clienthouse.com/images/f106e78f34/CH_location_web1.jpg').getContent();

 

 

And received a well handled java.net.ConnectException! At this point I got a little frustrated.

 

What' s really annoying me is actually not the fact that this is not working. I could understand if Apex had the following two limitations:

:: HTTP classes only support text based content like XML or HTML : alright!

:: PageReference.getContent() only supports content from the salesforce.com domain : acceptable!

 

But all of this is not documented (!!) and this makes it a real pain.

 

Best regards,

Henry

 

joshbirkjoshbirk

Here's an older post with the same outcome:

http://boards.developerforce.com/t5/Apex-Code-Development/How-to-return-binary-data-from-an-External-web-service-callout/td-p/154724

 

What's the specific use case, Henry?  Anything on the other end which could convert it to base64?  How much control do you have over the server hosting the image?

TerryLuschenTerryLuschen

I found a link that knows how to do this...

http://stackoverflow.com/questions/9632570/upload-image-from-android-client-to-salesforce-custom-object

 

In the recent Spring release (v24) ... you can now work with binary data (blobs in apex) directly in the http request or response. Here's an example of making a HTTP GET request for an image PNG file, and saving it to the document object in salesforce.

 

Here is the code in that link:

 

HttpRequest r = new HttpRequest();
r.setMethod('GET');
r.setEndpoint('http://www.pocketsoap.com/osx/soqlx/soqlxicon.png');
Http http = new Http();
HttpResponse res = http.send(r);
blob image = res.getBodyAsBlob();

Document d = new Document();
d.name = 'logo.png';
d.body = image;
d.folderId = UserInfo.getUserId();
insert d;
system.debug(d.id);

This was selected as the best answer