show preview of pdf file saved in gridfs on browser - php

I'm using gridfs to store files in MongoDB. I'm facing a problem when I try to show the large pdf file in the browser, which is saved in gridfs. Large files don't show up in the browser, but small files does.
This is the service code
public function getIpFileByFileId() {
$request = $this->request;
$dm = $this->container->get('doctrine_mongodb')->getManager('patient');
$id = $request->get('fileId');
//get doc
$docIpMapping = $dm->getRepository('PatientDocumentsBundle:IPDocuments')->findOneBy([
'id' => $id
]);
$base64 = (base64_encode($docIpMapping->getFile()->getBytes()));
$response['data'] = $base64;
$response['msg'] = 'success';
return $response;
}
And this is the front end code
Ajax(path, data).success(function (result) {
$("#pdfDiv").html('<iframe style="width:100%;height:500px;" src="data:application/pdf;base64,' + result.data + '"></iframe>');
});
Does the code have any issues? How do I display large files in the front end?

Here is my suggestion, without open in new tab,
http://answerexpress.blogspot.com/2018/09/show-preview-of-pdf-file-saved-in.html

Related

How to return json response and Storage data together in Laravel?

I'm trying to return query data and storage Images from laravel controller. My code looks like following :
class ClaimController extends Controller{
.....
public function show(Claim $claim)
{
$front_image = Storage::disk('do_spaces')->get($claim->images->front_image); //image file
$back_image = Storage::disk('do_spaces')->get($claim->images->back_image); //image
// return $front_image [works]
$claim = Claim::all();
//this throws error
return response()->json([
'claim' => $claim,
'images' => [$front_image, $back_image]
]);
}
}
Now I far I understand return->response()->json([]) doesn't send image file. How I can return all data together to frontend app ?
you have the option to return the images from original server which they are stored in or you can return an encoded version of the image as string and in front end reconstruct it.
$path = 'myfolder/myimage.png';
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
And then use it in front like this :
var image = new Image();
image.src = 'data:image/png;base64,iVBORw0K...';
document.body.appendChild(image);
This is the link for second part.
You can use Storage::url()
$st=\Illuminate\Support\Facades\Storage::disk('do_spaces')->url($claim->images->front_image);
dd(url($st));
Storage::url() return image path and then url() will return full url path
"http://127.0.0.1:8000/storage/imagefolder/filename"
Make sure to symbolic link to storage folder by running following command
php artisan storage:link
Also you can do the following without storage url
asset('storage/'.$claim->images->front_image)

Symfony2 Filesystem - Save a stream of data in an existent directory

I have a data stream that I need to save in a PDF file and then store that file in an already existent directory, which is Documents/pdf. This directory is at the same level of src, app, web directories, and has all the permissions to write in it.
With my solution I always have the file saved under the web directory. I want the file to be under Documents/pdf. This is my controller:
/**
* #Route("/api/savePdf", name = "save_pdf")
* #Method("POST")
**/
public function savePdfAction(Request $request) {
$pdfPath = $this->get("kernel")->getRootDir() . '/../Documents/pdf/';
$data = $request->getContent();
$name = 'file.pdf';
$dateNow = new \DateTime('now');
$date = $dateNow->format('Y-m-d H-i-s');
$fileName = $date.$name;
try {
$fs = new Filesystem();
$fs->dumpFile($fileName, $data);
move_uploaded_file($fileName, $pdfPath.$fileName);
return new Response ("File saved correctly", 200, array('Content-Type' => 'application/json') );
}
catch(IOException $e) {
return new Response ("Error!", 500, array('Content-Type' => 'application/json'));
}
return new Response();
}
Don't use
move_uploaded_file
http://php.net/manual/en/function.move-uploaded-file.php
This function checks to ensure that the file designated by filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload mechanism).
I'm just guessing here but since you dump the content to a file yourself i don't think it does satisfy the move_uploaded_file usage condition.
Why don't you dump the content directly into the targetfolder and get rid of a manual move?
$fs->dumpFile($pdfPath.$fileName, $data);
should do the trick since your path is absolute anyways.

Why after I uploaded an image to Azure I cannot access it?

I'm developing a Universal App for Windows Phone 8.1 but I'm using a PHP Page to get recognize some patterns from an Image that I uploaded to my service.
I have discovered that after I uploaded X image to Azure, I cannot use it. I'm using WebMatrix to develop my PHP Page and when I refresh it, it doesn't show me the images that I uploaded however when I try to publish something and I select the option: "Delete files on the remote server that are not on my computer." I can see my images. This is an example of my PHP code:
$uploaddir = getcwd();
$uploadfile = $uploaddir . "/" . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
chmod($uploadfile, 0755);
$Test = new Display($_FILES['userfile']['name']);
echo '{"result": "' . $Test->getNumber($_REQUEST['color'], false) . '"}';
//unlink($uploadfile);
} else {
echo '{"result": "-1"}';
}
I'd like to know what could be my bug because I don't understand why I can access from the URL, too to the bit I cannot use it, maybe it's how I assigned the permissions but with or without the chmod, it doesn't change at all. I have even tried other hostings and the problem is the same when I enter the File Manager, there are only my PHP files and it doesn't allow me to manage the image.
This is my Windows Phone code to upload the Image if it's necessary:
byte[] ConvertBitmapToByteArray()
{
WriteableBitmap bmp = bitmap;
using (Stream stream = bmp.PixelBuffer.AsStream())
{
MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
public async Task<string> Upload()
{
try
{
using (var client = new HttpClient())
{
using (var content =
new MultipartFormDataContent())
{
byte[] data = ConvertBitmapToByteArray();
using (var stream = new InMemoryRandomAccessStream())
{
// encoder *outputs* to stream
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
// encoder's input is the bitmap's pixel data
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight,
(uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96, 96, data);
await encoder.FlushAsync();
content.Add(new StreamContent(stream.AsStream()), "userfile", fileNewImage);
using (
var message =
await client.PostAsync("http://xplace.com/uploadtest.php", content))
{
var input = await message.Content.ReadAsStringAsync();
return input;
}
}
}
}
}
catch (Exception ex)
{
return null;
}
}
Thanks for your worthy knowledge and experience.
Create a blob storage account, and add a public container. In your action to save the file, store the file in you blob storage container. Then you can access the image as you would with any other image.
Here is a tutorial on Azure: http://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-how-to-use-blobs/
Also, you cannot create folders in a container, but you could use a naming convention on the blobrefname to create the idea of a container. Also, you can attach a domain to the cloud service if you want the URL to have a certain look.
READ YOUR QUESTION AGAIN - And it looks like it's more on the client side.
Here is what I usually do to attach a file to a MultipartFormDataContent:
MultipartFormDataContent content = new MultipartFormDataContent();
FileInfo info = new FileInfo(currFileLoc);
string contentMediaType = null;
//This is a Dictionary<string, string> that takes in the file
//extension, and returns the media type (e.g. "image/jpeg")
GlobalVariables.ApprovedMediaTypes.TryGetValue(
info.Extension.ToLower()
, out contentMediaType);
//If the dictionary doesn't return a result
//then it's not a supported file type
if (contentMediaType == null)
throw new Exception(
String.Format("The file \"{0}\" is an unsupported file type."
, info.Name));
ByteArrayContent currFile = new ByteArrayContent(File.ReadAllByte(currFileLoc));
currFile.Headers.ContentType = new MediaTypeWithQualityHeaderValue(contentMediaType);
content.Add(currFile, currFileLoc, currFileLoc);
The I make my call. Maybe you found another option with blob storage. Finally, if you load large files, you may want to look into uploading in chunks.

php, data not updating after form post in zend?

this might be a bit of a novice question and here is my situation:
i have a upload form for uploading images. and in my editAction i do:
if ($request->isPost()) {
if (isset($_POST['upload_picture']) && $formImageUpload->isValid($_POST)) {
//here i will add the picture name to my database and save the file to the disk.
}
}
$picVal = $this->getmainPic(); // here i do a simple fetch all and get the picture that was just uploaded
$this->view->imagepath = $picVal;
what happens is that the newly uploaded picture doesn't show. I checked the database and the dick and the file is there.
im thinking the problem might be the order of the requests or something similar.
any ideas?
edit: another thing is that in order to make the new image come up i have to do a SHIFT+F5 and not only press the browser refresh button
edit2: more code
i first call the upload to disk function then if that returns success addthe file to the database
$x = $this->uploadToDiskMulty($talentFolderPath, $filename)
if($x == 'success'){
$model->create($data);
}
the upload function
public function uploadToDiskMulty($talentFolderPath, $filename)
{
// create the transfer adapter
// note that setDestiation is deprecated, instead use the Rename filter
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addFilter('Rename', array(
'target' => $filename,
'overwrite' => true
));
// try to receive one file
if ($adapter->receive($talentFolderPath)) {
$message = "success";
} else {
$message = "fail";
}
return $message;
}
If the picture only appears when you do SHIFT+F5 that means it's a caching problem. Your browser doesn't fetch the image when you upload it. Do you use the same file name?

displaying blob images - symfony

I have blob data in my database and they are images that I want to display as a basic gallery.
I have a method that I have written to display the images, but I'm getting an error, saying that it is a string, rather than blob data being returned:
public function getFilenamePath()
{
$file_src = false;
if (null !== $fp = $this->getFilename())
{
$file = stream_get_contents($fp);
$file_src = '/uploads/gallery/'.$this->getId().'.jpg';
}
return $file_src;
}
where getFilename() is my blob column.
action:
public function executeSingle(sfWebRequest $request)
{
$application_id = $this->getRequestParameter('id');
$c = new Criteria();
$c->addJoin(GalleryPeer::APPLICATION_ID, ApplicationPeer::ID);
$c->addJoin(GalleryImagePeer::GALLERY_ID, GalleryPeer::ID);
$c->add(GalleryPeer::APPLICATION_ID, $application_id);
$this->galleries = GalleryImagePeer::doSelect ( $c );
}
template:
foreach($galleries as $gallery)
{
$path = $gallery->getFilenamePath();
if($path)
{
echo '<img src="'.$path.'" />';
}
}
The error I get is that stream_get_contents seems to be returning a string.
Is there anyway, I can get the blob data, or rather than use a model method, use an action to return all the images attached to the application?
Thanks
If you store images in the database, you have (basically) two options to show them on the client:
First solution: Get file content and encode it with base64 encoding. You can find a working example here:
http://www.php.net/manual/en/function.base64-encode.php#99842
This method is not the best as if you do it like that, the client won't be able to cache these images, that means more traffic, more processing time, more database connection, slower page loading etc.
Second solution: You create an image loading action in Symfony. The routing is like:
mapimage:
url: /myimage/:image_id.png
param: { module: myimagemodul, action: myimageaction }
You have to create a controller action myimageaction and there you can get the image ID like
$request->getParameter('image_id');
And get the blob data from the database and return it as binary with specific http headers. You can find working examples with simple Googleing, one example:
$this->image = ImagePeer::retrieveByPk ($request->getParameter('image_id'));
$response = $this->getResponse();
$response->clearHttpHeaders();
$response->setContentType ($this->image->getMimeType());
$response->setHttpHeader ('Content-Disposition', 'inline;filename='.$filename);
$content = $this->image->getData();
$response->setContent (stream_get_contents ($content));
$this->setLayout (false);
return sfView::NONE;
So in the template you can do like:
<img src='<?= url_for ('route_to_action_above', array ('image_id' => $image->getId()) ?>'/>
I have found this one at
http://forum.symfony-project.org/viewtopic.php?f=22&t=31207#p109705
This code doesn't make any sense.
Why do you feed binary(read string) data from ->getFilename() to stream_get_contents() which operates ONLY on resource data type? Of course it will complain.
Outputing blob to a browser is as simple as:
$this->getResponse->setContentType('image/jpeg');
echo $data->getFilename(); // assuming filename column is your blob column
try switching your getFilenamePath function to this.
public function getFilenamePath() {
$file_src = '/uploads/gallery/'.$this->getId().'.jpg';
if (file_exists($file_src ) {
return $file_src;
} else {
return false;
}
}
$profile_picture = base64_encode(stream_get_contents($image->getContent()));
echo '<img src="data:image/jpeg;base64,'.$profile_picture.'" />';

Categories