/    Sign up×
Community /Pin to ProfileBookmark

Image file corrupted???

Hi,

i have created a File repository to store my .jpg image files in a database called filestore. I can easily store them in my database and can extract the information about the files to be displayed in my browser. Next to each file is a download button, when i try to download the file and try to view it, i get a message from Windows Photo gallery saying:
[B]Photo gallery can’t open this picture or video. The file seems to be damaged or corrupted[/B]

[CODE] code snippet
if(isset($_GET[‘action’]) and ($_GET[‘action’] == ‘view’ or $_GET[‘action’] == ‘download’) and isset($_GET[‘id’]) )
{
include ‘db.inc.php’;
$id = mysqli_real_escape_string($link, $_GET[‘id’]);

$sql = “SELECT filename, mimetype, filedata FROM filestore WHERE id =’$id'”;

$result = mysqli_query($link, $sql);
if(!$result)
{
$error = ‘Database error fetching requested file’;
include $_SERVER[‘DOCUMENT_ROOT’] . ‘/includes/error.html.php’;
exit();
}

$file = mysqli_fetch_array($result);
if(!$file)
{
$error = ‘File with specified ID not found in filestore db’;
include $_SERVER[‘DOCUMENT_ROOT’] . ‘/includes/error.html.php’;
exit();
}

// Use variables to send the data in http headers
$filename = $file[‘filename’];
$mimetype = $file[‘mimetype’];
$filedata = $file[‘filedata’];
$disposition = ‘inline’; // use to download

if($_GET[‘action’] == ‘download’)
{
$mimetype = ‘application/octet-stream’; // force download in older browsers
$disposition = ‘attachment’;
}

// Content-type must come before Content-disposition
header(“Content-type: $mimetype”);
header(“Content-disposition: $disposition; filename=$filename”); // force the browser to display save dialog for download
header(‘Content-length: ‘ . strlen($filedata) );

echo $filedata;
exit();
}

[/CODE]

html form, files.html.php

[CODE]
<?php include_once $_SERVER[‘DOCUMENT_ROOT’] .
‘/includes/helpers.inc.php’; ?>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”
“http://www.w3.org/TR/html4/strict.dtd”
>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
<head>
<title>PHP/MYSQL File Repository</title>
<meta http-equiv=”content-type”
content=”text/html; charset=utf-8″ />

</head>
<body>
<h1> PHP/MYSQL File Repository </h1>
<!– multipart/form-data ensures the actual file is sent with the form data –>
<form action=” ” method=”post” enctype=”multipart/form-data”>
<div><label for=”upload”> Select file to upload: <input type=”file” id=”upload” name=”upload”/></label></div>

<div>
<label for=”desc”>File Description <input type=”text” id=”desc” name=”desc” maxlength=”255″ /></label>
</div>

<div>
<input type=”hidden” name=”action” value=”upload”/>
<input type=”submit” value=”Submit”/>
</div>
</form>
<?php if(count($files) > 0): ?>
<p> The following are files stored in the filestore database:</p>

<table>
<thead>
<tr>
<th>File Name </th>
<th> Type </th>
<th> Description </th>
</tr>
</thead>

<tbody>
<?php foreach($files as $f) :?>
<tr valign=”top”>
<td>
<a href=”?action=view&amp; id=<?php htmlout($f[‘id’]); ?>” >
<?php htmlout($f[‘filename’]); ?></a>
</td>

<td><?php htmlout($f[‘mimetype’]); ?></td>
<td><?php htmlout($f[‘description’]); ?></td>

<td>
<form action=” ” method=”get”>
<div>
<input type=”hidden” name=”action” value=”download” />
<input type=”hidden” name=”id” value=”<?php htmlout($f[‘id’]); ?>”/>
<input type=”submit” value=”Download” />
</div>
</form>
</td>

<td>
<form action=” ” method=”post”>
<div>
<input type=”hidden” name=”action” value=”delete” />
<input type=”hidden” name=”id” value=”<?php htmlout($f[‘id’]); ?>” />
<input type=”submit” value=”Delete” />
</div>
</form>
</td>
</tr>
<?php endforeach ;?>
</tbody>
</table>
<?php endif ;?>

</body>
</html>

[/CODE]

what do i need to do to ensure that i can successfully view my image files?

to post a comment
PHP

14 Comments(s)

Copy linkTweet thisAlerts:
@nvidiaauthorMay 20.2010 — I went to where the files are save and tried to open them in another program like paint but i can see the files fine. Does anybody know why i seem to get this error after i try to download my .JPG files???

anybody
Copy linkTweet thisAlerts:
@criterion9May 20.2010 — Where is $file['$filedata'] being set?
Copy linkTweet thisAlerts:
@nvidiaauthorMay 21.2010 — here,
[CODE]

// Use variables to send the data in http headers
$filename = $file['filename'];
$mimetype = $file['mimetype'];
$filedata = $file['filedata'];
$disposition = 'inline'; // use to download
[/CODE]


In the download section of the IF statement.,
Copy linkTweet thisAlerts:
@criterion9May 21.2010 — here,
[CODE]

// Use variables to send the data in http headers
$filename = $file['filename'];
$mimetype = $file['mimetype'];
$filedata = $file['filedata'];
$disposition = 'inline'; // use to download
[/CODE]


In the download section of the IF statement.,[/QUOTE]


This is where $filename is being set to $file['filename']...where are $file['filename'] and $file['filedata'] being set?
Copy linkTweet thisAlerts:
@nvidiaauthorMay 21.2010 — Nowhere, it is simplly being assigned to those values given in that code section i gave you and then used in the:

[CODE]

// Content-type must come before Content-disposition
header("Content-type: $mimetype");
header("Content-disposition: $disposition; filename=$filename"); // force the browser to display save dialog for download
header('Content-length: ' . strlen($filedata) );

echo $filedata;
exit();
[/CODE]


and displayed in the form.
Copy linkTweet thisAlerts:
@criterion9May 21.2010 — Nowhere, it is simplly being assigned to those values given in that code section i gave you and then used in the:

[CODE]

// Content-type must come before Content-disposition
header("Content-type: $mimetype");
header("Content-disposition: $disposition; filename=$filename"); // force the browser to display save dialog for download
header('Content-length: ' . strlen($filedata) );

echo $filedata;
exit();
[/CODE]


and displayed in the form.[/QUOTE]

If it is not set anywhere then your contents of $filename, $filedata, etc would be empty...so, I'll ask again, where is the array $file being set?

Hint: It will look something like
[code=php]
$file['filename'] = "something will be on this side";
[/code]

or
[code=php]
$file = Array('filename'=>"something here");
[/code]
Copy linkTweet thisAlerts:
@nvidiaauthorMay 22.2010 — It isn't really set like that, when the user hit's the download button, it retrievies the data based on the ID and uses a select statement stored in the $result variable.

Here is my full php code so you can see how i'm doing it.

index.php
[code=php]

include $_SERVER['DOCUMENT_ROOT'] . '/includes/magicquotes.inc.php';

if(isset($_POST['action']) and $_POST['action'] == 'upload')
{

// Bail out if the file is not really an upload
if(!is_uploaded_file($_FILES['upload']['tmp_name']))
{
$error = 'There was no file uploaded';

include $_SERVER['DOCUMENT_ROOT'] . '/includes/error.html.php';
exit();

}

// When the form is submitted, store the name in temp variable, orignal name, type, desc and it's mime type
$uploadfile = $_FILES['upload']['tmp_name'];
$uploadname = $_FILES['upload']['name'];
$uploadtype = $_FILES['upload']['type'];
$uploaddesc = $_POST['desc'];
$uploaddata = file_get_contents($uploadfile);

include 'db.inc.php';

// Prepare for user-submitted values for safe database insert
$uploadname = mysqli_real_escape_string($link, $uploadname);
$uploadtype = mysqli_real_escape_string($link, $uploadtype);
$uploaddesc = mysqli_real_escape_string($link, $uploaddesc);
$uploaddata = mysqli_real_escape_string($link, $uploaddata);

$sql = "INSERT INTO filestore SET
filename = '$uploadname', mimetype = '$uploadtype', description = '$uploaddesc', filedata='$uploaddata'";
if(!mysqli_query($link, $sql))
{
$error = 'Database error in storing file!';
include $_SERVER['DOCUMENT_ROOT'] . '/includes/error.html.php';
exit();
}

header('Location: .');
exit();
}

// Retrive the file to be downloaded/viewed
if(isset($_GET['action']) and ($_GET['action'] == 'view' or $_GET['action'] == 'download') and isset($_GET['id']) )
{
include 'db.inc.php';
$id = mysqli_real_escape_string($link, $_GET['id']);

$sql = "SELECT filename, mimetype, filedata FROM filestore WHERE id ='$id'";

$result = mysqli_query($link, $sql);
if(!$result)
{
$error = 'Database error fetching requested file';
include $_SERVER['DOCUMENT_ROOT'] . '/includes/error.html.php';
exit();
}

$file = mysqli_fetch_array($result);
if(!$file)
{
$error = 'File with specified ID not found in filestore db';
include $_SERVER['DOCUMENT_ROOT'] . '/includes/error.html.php';
exit();
}

// Use variables to send the data in http headers
$filename = $file['filename'];
$mimetype = $file['mimetype'];
$filedata = $file['filedata'];
$disposition = 'inline'; // use to download

if($_GET['action'] == 'download')
{
$mimetype = 'application/octet-stream'; // force download in older browsers
$disposition = 'attachment';
}

// Content-type must come before Content-disposition
header("Content-type: $mimetype");
header("Content-disposition: $disposition; filename=$filename"); // force the browser to display save dialog for download
header('Content-length: ' . strlen($filedata) );

echo $filedata;
exit();
}

if(isset($_POST['action']) and $_POST['action'] == 'delete' and isset($_POST['id']))
{
include 'db.inc.php';
$id = mysqli_real_escape_string($link, $_POST['id']);

$sql = "DELETE FROM filestore WHERE id ='$id'";
if(!mysqli_query($link, $sql))
{
$error = 'Database error deleting requested file';
include $_SERVER['DOCUMENT_ROOT'] . '/includes/error.html.php';
exit();
}

header('Location: .');
exit();
}

include 'db.inc.php';


$sql = 'SELECT id, filename, mimetype, description FROM filestore';
$result = mysqli_query($link, $sql);
if(!$result)
{
$error = 'Database error fetching stored files';
include $_SERVER['DOCUMENT_ROOT'] . '/includes/error.html.php';
exit();
}


$files = array();
while($row = mysqli_fetch_array($result) )
{
$files[] = array('id' => $row['id'], 'filename' => $row['filename'], 'mimetype' => $row['mimetype'],
'description' => $row['description']);
}
include 'files.html.php';
?>


[/code]
Copy linkTweet thisAlerts:
@criterion9May 22.2010 — I've always had troubles actually storing image data in a table and usually just store a reference to it. Is it possible the DB is altering the data because of a size or type restriction?
Copy linkTweet thisAlerts:
@Jarrod1937May 22.2010 — If you're storing the actual image in a table can we see the create statement for it?
Copy linkTweet thisAlerts:
@nvidiaauthorMay 23.2010 — I've always had troubles actually storing image data in a table and usually just store a reference to it. Is it possible the DB is altering the data because of a size or type restriction?[/QUOTE]

It could be, i think it altering the data when i want to download it, but i adjusted the max_allowed_packet var in the my.ini file on my WAMP server, to handle files of up 16mb's
Copy linkTweet thisAlerts:
@nvidiaauthorMay 23.2010 — If you're storing the actual image in a table can we see the create statement for it?[/QUOTE]

I am assuming you mean the create table statement, here it is:

[CODE]CREATE TABLE filestore (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
filename VARCHAR(255) NOT NULL,
mimetype VARCHAR(50) NOT NULL,
description VARCHAR(255) NOT NULL,
filedata MEDIUMBLOB
) DEFAULT CHARACTER SET utf8;[/CODE]


Although, i checked my tables to see if the file sizes were being changed after i uploaded it, but the sizes seem to be the same. Do you think i should recreate this table?
Copy linkTweet thisAlerts:
@nvidiaauthorMay 25.2010 — Do you guys think that it would be best to create a PHP file system to manage my image files? If so, would i still need to use my db to store the text string of the file name or a name associatived with the file?
Copy linkTweet thisAlerts:
@criterion9May 25.2010 — That is how I usually handle uploaded images in my PHP applications.
Copy linkTweet thisAlerts:
@Jarrod1937May 25.2010 — Sorry for not getting back to you, been busy.

The create statement shows your blob field should be able to hold up to 16mb (if i remember mediumblob correctly), so you should be fine unless your images are exceeding that. My original theory is that you may be using something like tinyblob and the image binary data is being chopped off, but that is unlikely with a 16mb limit. So with that said, i am still not sure why your current method isn't working. But if your table size isn't even being changed then something very fishy is going on, either your upload is failing or you're not correctly inserting the uploaded image into the table. If you want to go the db route for image storage i'd recommend checking that the binary data exist in each and every step, somewhere its getting lost. You can then also try to find the size of the output of the retrieved data to see if it matches what went in.

However, yes it would be better to use a filesystem for the image storage and simply save a reference to the image in the database. It is actually faster than a db image storage method, i would have suggested it earlier but i figured you had a particular reason for using a database for the binary storage.
×

Success!

Help @nvidia spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 6.17,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @nearjob,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,
)...