Merge branch 'mediafile_fromfilehandle_avatar' into 'master'
MediaFile::fromFilehandle on profile avatar upload This is mainly because I in GNU social want to change the constructor of MediaFile and thus use fromFilehandle in Qvitter, so we don't have to sync the changes as much. This also will make sure that uploaded files can be reused if they match a SHA256 hash of the avatar we want to set. Parts of my rewriting also provide a pretty good example of how we can reuse existing File entries as Avatar sources. See merge request !34
This commit is contained in:
commit
68b3d377e8
|
@ -78,44 +78,27 @@ class ApiAccountUpdateProfileBannerAction extends ApiAuthAction
|
||||||
protected function handle()
|
protected function handle()
|
||||||
{
|
{
|
||||||
parent::handle();
|
parent::handle();
|
||||||
$profile = $this->user->getProfile();
|
|
||||||
|
|
||||||
// see if we have regular uploaded image data
|
// see if we have regular uploaded image data
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$mediafile = MediaFile::fromUpload('banner', $profile);
|
$mediafile = MediaFile::fromUpload('banner', $this->scoped);
|
||||||
|
|
||||||
} catch (NoUploadedMediaException $e) {
|
} catch (NoUploadedMediaException $e) {
|
||||||
|
|
||||||
// if not we may have base64 data
|
// if not we may have base64 data
|
||||||
$img = $this->img;
|
|
||||||
if(stristr($img, 'image/jpeg')) {
|
|
||||||
$img_mime = 'image/jpeg';
|
|
||||||
}
|
|
||||||
elseif(stristr($img, 'image/png')) {
|
|
||||||
// should convert to jpg here!!
|
|
||||||
$img_mime = 'image/png';
|
|
||||||
}
|
|
||||||
|
|
||||||
// i don't remember why we had to do this
|
$this->img = str_replace('data:image/jpeg;base64,', '', $this->img);
|
||||||
$img = str_replace('data:image/jpeg;base64,', '', $img);
|
$this->img = str_replace('data:image/png;base64,', '', $this->img);
|
||||||
$img = str_replace('data:image/png;base64,', '', $img);
|
$this->img = str_replace(' ', '+', $this->img);
|
||||||
$img = str_replace(' ', '+', $img);
|
$this->img = base64_decode($this->img, true);
|
||||||
$img = base64_decode($img, true);
|
|
||||||
|
|
||||||
try {
|
$fh = tmpfile();
|
||||||
$img_filename = File::filename($profile, 'cover', $img_mime);
|
fwrite($fh, $this->img);
|
||||||
$img_path = File::path($img_filename);
|
unset($this->img);
|
||||||
$img_success = file_put_contents($img_path, $img);
|
fseek($fh, 0);
|
||||||
$img_mimetype = MediaFile::getUploadedMimeType($img_path, $img_filename);
|
|
||||||
$mediafile = new MediaFile($profile, $img_filename, $img_mimetype);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->clientError($e, 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$mediafile instanceof MediaFile) {
|
$mediafile = MediaFile::fromFilehandle($fh, $this->scoped);
|
||||||
$this->clientError(_('Could not process image data.'), 400);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe resize
|
// maybe resize
|
||||||
|
@ -132,16 +115,27 @@ class ApiAccountUpdateProfileBannerAction extends ApiAuthAction
|
||||||
|
|
||||||
// crop
|
// crop
|
||||||
try {
|
try {
|
||||||
$imagefile = new ImageFile($mediafile->fileRecord->id, File::path($mediafile->filename));
|
$imagefile = ImageFile::fromFileObject($mediafile->fileRecord);
|
||||||
$imagefile->resizeTo(File::path($mediafile->filename), array('width'=>$width, 'height'=>$height, 'x'=>$this->cropX, 'y'=>$this->cropY, 'w'=>$this->cropW, 'h'=>$this->cropH));
|
unset($mediafile);
|
||||||
$result['url'] = File::url($mediafile->filename);
|
|
||||||
|
// We're just using the Avatar function to build a filename here
|
||||||
|
// but we don't save it _as_ an avatar below... but in the same dir!
|
||||||
|
$filename = Avatar::filename(
|
||||||
|
$this->scoped->getID(),
|
||||||
|
image_type_to_extension($imagefile->preferredType()),
|
||||||
|
null,
|
||||||
|
'banner-'.common_timestamp()
|
||||||
|
);
|
||||||
|
|
||||||
|
$imagefile->resizeTo(Avatar::path($filename), array('width'=>$width, 'height'=>$height, 'x'=>$this->cropX, 'y'=>$this->cropY, 'w'=>$this->cropW, 'h'=>$this->cropH));
|
||||||
|
$result['url'] = Avatar::url($filename);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->clientError(_('The image could not be resized and cropped. '.$e), 422);
|
$this->clientError(_('The image could not be resized and cropped. '.$e), 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save in profile_prefs
|
// save in profile_prefs
|
||||||
try {
|
try {
|
||||||
Profile_prefs::setData($profile, 'qvitter', 'cover_photo', $result['url']);
|
Profile_prefs::setData($this->scoped, 'qvitter', 'cover_photo', $result['url']);
|
||||||
} catch (ServerException $e) {
|
} catch (ServerException $e) {
|
||||||
$this->clientError(_('The image could not be resized and cropped. '.$e), 422);
|
$this->clientError(_('The image could not be resized and cropped. '.$e), 422);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,15 @@ class ApiUpdateAvatarAction extends ApiAuthAction
|
||||||
$this->cropY = $this->trimmed('cropY');
|
$this->cropY = $this->trimmed('cropY');
|
||||||
$this->img = $this->trimmed('img');
|
$this->img = $this->trimmed('img');
|
||||||
|
|
||||||
|
$this->img = str_replace('data:image/jpeg;base64,', '', $this->img);
|
||||||
|
$this->img = str_replace('data:image/png;base64,', '', $this->img);
|
||||||
|
$this->img = str_replace(' ', '+', $this->img);
|
||||||
|
$this->img = base64_decode($this->img);
|
||||||
|
|
||||||
|
if (empty($this->img)) {
|
||||||
|
throw new ClientException(_('No uploaded image data.'));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,47 +88,34 @@ class ApiUpdateAvatarAction extends ApiAuthAction
|
||||||
{
|
{
|
||||||
parent::handle();
|
parent::handle();
|
||||||
|
|
||||||
$profile = $this->user->getProfile();
|
$imagefile = null;
|
||||||
$base64img = $this->img;
|
// write the image to a temporary file
|
||||||
if(stristr($base64img, 'image/jpeg')) {
|
$fh = tmpfile();
|
||||||
$base64img_mime = 'image/jpeg';
|
fwrite($fh, $this->img);
|
||||||
}
|
unset($this->img); // no need to keep it in memory
|
||||||
elseif(stristr($base64img, 'image/png')) {
|
// seek back to position 0, so we don't read EOF directly
|
||||||
// should convert to jpg here!!
|
fseek($fh, 0);
|
||||||
$base64img_mime = 'image/png';
|
// read the temporary file as an uploaded image, will store File object
|
||||||
}
|
$mediafile = MediaFile::fromFilehandle($fh, $this->scoped);
|
||||||
$base64img = str_replace('data:image/jpeg;base64,', '', $base64img);
|
// Deletes the temporary file, if it was needed we stored it in fromFilehandle
|
||||||
$base64img = str_replace('data:image/png;base64,', '', $base64img);
|
fclose($fh);
|
||||||
$base64img = str_replace(' ', '+', $base64img);
|
|
||||||
$base64img_hash = md5($base64img);
|
|
||||||
$base64img = base64_decode($base64img);
|
|
||||||
$base64img_basename = basename('avatar');
|
|
||||||
$base64img_filename = File::filename($profile, $base64img_basename, $base64img_mime);
|
|
||||||
$base64img_path = File::path($base64img_filename);
|
|
||||||
$base64img_success = file_put_contents($base64img_path, $base64img);
|
|
||||||
$base64img_mimetype = MediaFile::getUploadedMimeType($base64img_path, $base64img_filename);
|
|
||||||
$mediafile = new MediaFile($profile, $base64img_filename, $base64img_mimetype);
|
|
||||||
$imagefile = new ImageFile($mediafile->fileRecord->id, File::path($mediafile->filename));
|
|
||||||
$imagefile->resizeTo(File::path($mediafile->filename), array('width'=>$this->cropW, 'height'=>$this->cropH, 'x'=>$this->cropX, 'y'=>$this->cropY, 'w'=>$this->cropW, 'h'=>$this->cropH));
|
|
||||||
|
|
||||||
$type = $imagefile->preferredType();
|
// Now try to get it as an ImageFile since it has some handy functions
|
||||||
|
$imagefile = ImageFile::fromFileObject($mediafile->fileRecord);
|
||||||
|
unset($mediafile); // This isn't needed in memory.
|
||||||
|
|
||||||
|
// Get an appropriate filename for the avatar
|
||||||
$filename = Avatar::filename(
|
$filename = Avatar::filename(
|
||||||
$profile->id,
|
$this->scoped->getID(),
|
||||||
image_type_to_extension($type),
|
image_type_to_extension($imagefile->preferredType()),
|
||||||
null,
|
null,
|
||||||
common_timestamp()
|
common_timestamp()
|
||||||
);
|
);
|
||||||
|
$imagefile->resizeTo(Avatar::path($filename), array('width'=>$this->cropW, 'height'=>$this->cropH, 'x'=>$this->cropX, 'y'=>$this->cropY, 'w'=>$this->cropW, 'h'=>$this->cropH));
|
||||||
|
|
||||||
$filepath = Avatar::path($filename);
|
$this->scoped->setOriginal($filename);
|
||||||
|
|
||||||
$imagefile->copyTo($filepath);
|
$twitter_user = $this->twitterUserArray($this->scoped, true);
|
||||||
|
|
||||||
$profile = $this->user->getProfile();
|
|
||||||
$profile->setOriginal($filename);
|
|
||||||
|
|
||||||
$mediafile->delete();
|
|
||||||
|
|
||||||
$twitter_user = $this->twitterUserArray($profile, true);
|
|
||||||
$this->initDocument('json');
|
$this->initDocument('json');
|
||||||
$this->showJsonObjects($twitter_user);
|
$this->showJsonObjects($twitter_user);
|
||||||
$this->endDocument('json');
|
$this->endDocument('json');
|
||||||
|
|
|
@ -67,6 +67,15 @@ class ApiUpdateBackgroundImageAction extends ApiAuthAction
|
||||||
$this->cropY = $this->trimmed('cropY');
|
$this->cropY = $this->trimmed('cropY');
|
||||||
$this->img = $this->trimmed('img');
|
$this->img = $this->trimmed('img');
|
||||||
|
|
||||||
|
$this->img = str_replace('data:image/jpeg;base64,', '', $this->img);
|
||||||
|
$this->img = str_replace('data:image/png;base64,', '', $this->img);
|
||||||
|
$this->img = str_replace(' ', '+', $this->img);
|
||||||
|
$this->img = base64_decode($this->img);
|
||||||
|
|
||||||
|
if (empty($this->img)) {
|
||||||
|
throw new ClientException(_('No uploaded image data.'));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,31 +88,35 @@ class ApiUpdateBackgroundImageAction extends ApiAuthAction
|
||||||
{
|
{
|
||||||
parent::handle();
|
parent::handle();
|
||||||
|
|
||||||
$profile = $this->user->getProfile();
|
$imagefile = null;
|
||||||
$base64img = $this->img;
|
|
||||||
if(stristr($base64img, 'image/jpeg')) {
|
|
||||||
$base64img_mime = 'image/jpeg';
|
|
||||||
}
|
|
||||||
elseif(stristr($base64img, 'image/png')) {
|
|
||||||
// should convert to jpg here!!
|
|
||||||
$base64img_mime = 'image/png';
|
|
||||||
}
|
|
||||||
$base64img = str_replace('data:image/jpeg;base64,', '', $base64img);
|
|
||||||
$base64img = str_replace('data:image/png;base64,', '', $base64img);
|
|
||||||
$base64img = str_replace(' ', '+', $base64img);
|
|
||||||
$base64img_hash = md5($base64img);
|
|
||||||
$base64img = base64_decode($base64img);
|
|
||||||
$base64img_basename = basename('bg');
|
|
||||||
$base64img_filename = File::filename($profile, $base64img_basename, $base64img_mime);
|
|
||||||
$base64img_path = File::path($base64img_filename);
|
|
||||||
$base64img_success = file_put_contents($base64img_path, $base64img);
|
|
||||||
$base64img_mimetype = MediaFile::getUploadedMimeType($base64img_path, $base64img_filename);
|
|
||||||
$mediafile = new MediaFile($profile, $base64img_filename, $base64img_mimetype);
|
|
||||||
$imagefile = new ImageFile($mediafile->fileRecord->id, File::path($mediafile->filename));
|
|
||||||
$imagefile->resizeTo(File::path($mediafile->filename), array('width'=>1280, 'height'=>1280, 'x'=>$this->cropX, 'y'=>$this->cropY, 'w'=>$this->cropW, 'h'=>$this->cropH));
|
|
||||||
$result['url'] = File::url($mediafile->filename);
|
|
||||||
|
|
||||||
Profile_prefs::setData($profile, 'qvitter', 'background_image', $result['url']);
|
// put the image data in a temporary file
|
||||||
|
$fh = tmpfile();
|
||||||
|
fwrite($fh, $this->img);
|
||||||
|
unset($this->img);
|
||||||
|
fseek($fh, 0); // go to beginning just to be sure the content is read properly
|
||||||
|
|
||||||
|
// We get a MediaFile with a File object using the filehandle
|
||||||
|
$mediafile = MediaFile::fromFilehandle($fh, $this->scoped);
|
||||||
|
// and can dispose of the temporary filehandle since we're certain we have a File on disk now
|
||||||
|
fclose($fh);
|
||||||
|
|
||||||
|
$imagefile = ImageFile::fromFileObject($mediafile->fileRecord);
|
||||||
|
unset($mediafile); // No need to keep the MediaFile around anymore, everything we need is in ImageFile
|
||||||
|
|
||||||
|
// We're just using the Avatar function to build a filename here
|
||||||
|
// but we don't save it _as_ an avatar below... but in the same dir!
|
||||||
|
$filename = Avatar::filename(
|
||||||
|
$this->scoped->getID(),
|
||||||
|
image_type_to_extension($imagefile->preferredType()),
|
||||||
|
null,
|
||||||
|
'bg-'.common_timestamp()
|
||||||
|
);
|
||||||
|
|
||||||
|
$imagefile->resizeTo(Avatar::path($filename), array('width'=>1280, 'height'=>1280, 'x'=>$this->cropX, 'y'=>$this->cropY, 'w'=>$this->cropW, 'h'=>$this->cropH));
|
||||||
|
$result['url'] = Avatar::url($filename);
|
||||||
|
|
||||||
|
Profile_prefs::setData($this->scoped, 'qvitter', 'background_image', $result['url']);
|
||||||
|
|
||||||
$this->initDocument('json');
|
$this->initDocument('json');
|
||||||
$this->showJsonObjects($result);
|
$this->showJsonObjects($result);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user