use file_put_contents('test/xxx.jpg', $url), get wrong image - php

I use php. I try download a image from a url, my code worked for some url, and others don't work.I wanna my code to work for all url. Or tell me what lead to this.
here is My script:
$imgUrl = 'http://www.inc.com/uploaded_files/image/i-love-me_49961.jpg';
$imageData = file_put_contents('test/xxx.jpg', file_get_contents($imgUrl));
Right now, I can get this image file(xxx.jpg), but when I open saved file in ACDSee,I get nothing.
however, if I use "http://www.wired.com/wp-content/uploads/2014/11/faa-drones-ft-660x330.jpg", My script works.
Please help me.

Interesting. This is a case of file_get_contents failing to get the correct image, so to speak, but the best matched SO questions I found would not help you, because they are about different things.
I shall answer this by laying out how you should solve this type of problems.
Problem solving is the simple art of breaking down the problem, and check the smaller pieces one by one until the cause is pinpointed.
First, did you get anything saved?
If yes, that means you did get something, and we can exclude all data read write problems including file permissions, network problems, access denials, or lack of curl extension.
If you didn't get the saved file, these issues has to be checked one by one.
In your case, I trust that you did get the file.
So the problem is now with the actual data.
Usually, we first verify that the source is ok.
Open it in browser. Save it. Open saved file in ACDSee.
It works! This is how we confirm the source is working, and ACDSee is working.
(And that the OS/browser/network is working, actually.)
Which leave us the saved data.
No programs can open it as jpeg, so we can be pretty certain the saved file is not a jpeg.
What is it, then?
If you use a hex editor (e.g. HxD) to open the PHP saved file (not a jpeg) and the manually saved file (confirmed jpeg), you will see that they are simply totally different.
manually saved image: FF D8 FF E1 ...
PHP saved image: 1F 8B 08 ...
If you lookup these first few bytes, called file headers, you will see that the PHP saved file is a gzip file.
To confirm this, you can rename the file's extension to .gz. Unzip it, and viola there is the image!
Note: hex comparison is pretty useful in sorting out the occasional weird problems, such as unwanted bom markers, line break conversion on binary files, or messy server filters.
So hex editors are indispensable for a good programmer, even a web programmer.
At this stage, the question becomes, why did I get a gzipped file?
A web programmer should know what is wrong by now, but let's pretend we do not.
There is not much problem space left.
It is either file_put_contents or file_get_contents.
If you do a little PHP coding to get in between them, you will see that file_put_contents is returning the gzipped data.
But where did file_put_contents get its data?
From the network, of course!
Now, let me introduce your a software called Wireshark.
These software are called packet sniffers, and they can show you the raw data going through your network cable or wifi.
Note: Packet sniffers are not easy. You need to know network protocols really well to make sense of anything.
They belongs to a class of low level debuggers called system monitors, and are often the last resort.
But this final hand is one of the distinctions between an average programmer and an expert.)
Indeed, with a packet sniffer, we can confirm that the server is responding with gzip encoded content, using Content-Encoding: gzip.
And so, we now know that the real cause is file_get_contents does not automatically decompress gzip content.
With this correct question, stackoverflow already has answers.
This is how we approach pretty much every programming problems, and why we answer more than we ask.
Hope you enjoyed the journey, and hope you will become the tour guide one day.

Related

Moodle: Files uploaded via File API get corrupted when viewed

So I am developing a new course-format, in which a picture is associated with each activity in a course, and presented visually. I created the course format, overrode the renderer etc. That worked all fine. However, the images are supposed to be custom generated and since it has to work for all existing and future, I put some additional code into the general course module form, enabling an image upload.
After admittedly some struggle on my part to get the File API working, it now all works fine. Only in my course format, there is an additional heading, under which you can upload a single image. This gets saved to the database fine, it is not in draft and it is viewable in my dataroots filedir perfectly if I follow the contenthash in the database. It even gets loaded into the form as a default fine. However, if I try to work with the image, all tests run fine (.is_valid_img()etc) and I even get offered to download a file. However, when I do it is corrupted and my file viewer says: "Critical Error: Not a png file". Needless to say it is not displayed on my actual course site.
When I look at the file in filedir, it very clearly is a png. Please, I would be thankful for any help, since I have tried alot and am at my wits end.
It sounds to me like you are getting some sort of output on the page before the PNG file is sent - that would be added to the start of the file and cause it not to work as a PNG file.
I would suggest you open the file in a hex editor and check the start of the file - it should look like https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header, so look for extra characters before that.
As for where the extra characters come from - they may be an obvious warning / error message (which should be easy to track down and fix). Alternatively, you may have some stray 'echo' statements (again, fairly easy to track down). The worst problems to find are extra characters before the opening 'php' tags of a file somewhere in your install or after the closing tag at the end of a file (which is why you should never use closing PHP tags). Finding these will come down to searching through all your customised code files to locate them.

I have an entertaining "stuck file" issue

I'm in the process of creating a simple image admin tool that allows users to upload and delete images from a server. So far it's very basic stuff. I discovered that uploading files whose file name includes a blank space causes a problem - everything in the name up to the space is included in the uploaded file name, but nothing past that. The problem with this isn't so much broken image links (I can deal with those), but the images can't be deleted using my delete tool or the simplest "unlink" script. Once I discovered the problem and the cause, I contacted our support people and they cleared out the two problem files. Unfortunately, because of system constraints here at work, I don't have FTP access.
Now you'd think it's all resolved, but no. I added very clear warning messages - in bold red text - onto this prototype admin tool, and I let my boss and a few others know of the tool by email, explaining CLEARLY that file names with spaces don't work. So... what does my boss do? She uploaded two files with blanks in the file name.
So until I have a way to add an idiot filter into the script, can anyone suggest how I might be able to delete these two files? I'd even be willing to delete the populated directory and recreate it (none of the images there mean anything, just random stuff).
And if there's no advice about getting these things unstuck, is there any advice as to how I might prevent my boss from acting like a moron, short of cutting off her fingers?
my best answer would be, as you said, move all other files to another folder, delete folder, recreate folder.
After that, I'm thinking you need urlencode in your php to deal with weird characters and spaces in filenames.
One question that might help others, are you in Linux or Windows?
As a test, until it's working, try writing to a drive that you have access to so you can play until it works. Then switch to the live system. This way you don't have to call support to delete your tests.
Also, you could just substitute all spaces for underscores as a quick fix.
While deleting files using unlink() with their names having spaces in them, escape the spaces with "\". This will only work on Linux.

How can I embed a font without giving the user the ability to download it?

I know this is a bit contradicting seeing as the browser would have to download the font to render it but I was wondering if there is a way to host it where that it cannot be directly downloaded (or cached onto a user's computer for that matter).
A solution I came up with was to make a PHP script that hashes the current time to the second (adding a salt). If a particular variable in the GET request matches this hash then it will send out the header for the font's MIME type and then output the contents of the font file.
Then I would recreate the hash in the stylesheet and concatentate strings where that it would be a valid request to the PHP script.
That's the basic idea. I had it working. But there were two flaws in this:
If the browser requests the font on a different second, the PHP script would fail to match the hashes up, therefore, would output nothing thus the font would be the backup font (or the default font if none were provided)
If someone were quick enough, he/she could still download the font directly if he/she requested it on the same second (granted this would probably have to be a script that would do this.
Also does the browser cache the font anywhere (not that the caching would help since the hash in the URI would practically always be different).
EDIT: Are there any $_SERVER variables that I could utilize?
As the other answers say, it's very difficult (impossible) against someone that really wants to download it. There is pretty much always a way. However, to give you some ideas, this article describes how Typekit handles the problem.
If you expect the font to be useable by the browser for displaying your page, you MUST allow it be downloaded somehow. Once it's put onto the wire and sent to the browser, it is utterly out of your hands as to what the user will do with it.
You can only make it a bit harder to retrieve, and a knowledgeable user will bypass anything you do with trivial ease.
You can make it more difficult, as your solution does, however if your goal is to protect your font IP, it simply cannot be downloadable by a browser. You cannot control what the browser does no matter how hard you try, against a dedicated adversary.
What you can do though, perhaps, is provide server-side code to generate an image using your font, and serve that image instead. I assume you're not trying to prevent the user from seeing the rendering of this font, just from using the font directly?

PHP Large report file download issue

Solved
I actually found out what is going on here.
Turns out it was sending the whole file, but Excel (which I was using to open the result file for testing), will only display 65536 rows. If there are more than that, it will alert something to the effect of "the file is incompletely displayed" and then cut it off after that many records.
(Note to Joel Spolsky - please call your friends from the original Excel development team and yell at them for me =o)
Thanks!
I have a very simple script that pulls some data from a database, and sends it to the visitor as a .csv file.
I have the memory and execution time set to acceptable levels, but for a few large reports, I notice that the download cuts off after about 10 seconds.
This ONLY happens if I set it as a download in the headers. If I comment out the content-type, content-disposition, etc, and just write the data to the browser, then the entire file will download and display in the browser.
Code is as follows:
// Code removed.
Anyone have any ideas? Could this be a browser issue with file download?
Thanks!
I don't know what's causing your problem, but here is something that you can try:
Write the data to a file and then send it to the user using the X-Sendfile(see this) header. Alternatively you can redirect to the file.
I had a slightly similar issue, but with very slow downloads. The culprit was an overly aggressive antivirus package affecting only IE downloads. Check for Mcshield.exe.

Is there a different content-type for images with different color profile?

I have a script that will output a jpg, gif or png image. It uses the appropriate content-type according to the extension of the file (which in this case will be the right one always).
The problem is, I have a small number of files which will cause a 500 internal server error when I try to access them this way. However they work if I try to access them with a direct link.
These files have one difference: their color profile is not sRGB built-in, but instead it is "sRGB IEC61966-2.1", or "Uncalibrated".
Why am I getting an error?
My script: http://pastie.org/pastes/404257
EDIT: I changed from include to readfile and it worked. But I don't know why...
No, MIME types do not specify colour profiles. Everything needed to interpret a colour profile is embedded in the data of the image; there is no requirement for extra information at the basic transfer level in order to support colour profiles.
The problem was likely due to something else. For example, if you included them with PHP include(), then an occurence of the byte sequence '<?' may have caused the PHP parser to kick in, generating errors.
Changing to readfile() as you have done looks like the correct solution.
Note: the script you linked to has some serious security problems caused by lack of input validation. You may already know this and were just using it as a simplified example, in which case - hopefully nobody copies the code.

Categories