I am attempting to use an HTML form to display a "summary" section that contains an array of the headers (first row) of a spreadsheet file when the file is chosen and supplied to the File Input field of the form.
The AJAX request sends the file to the Wordpress backend where it is processed using wp_handle_upload, a PHP script attempts to identify the file type and create the appropriate Reader, then loads the file into the reader.
From here I would like to write some parsing script, unlink the file to get rid of PII for privacy compliance, then return the relevant information to the AJAX request.
public function tjg_csbs_ajax_get_spreadsheet_summary($file) {
// Pass file to wp_handle_upload
$upload = wp_handle_upload($file, array('test_form' => false));
// File type using IOFactory::identify()
$file_type = IOFactory::identify($upload['file']);
$reader = IOFactory::createReader($file_type);
// Pass upload to reader
try {
$spreadsheet = $reader->load($upload['file']);
unlink($upload['file']);
} catch (Exception $e) {
unlink($upload['file']);
wp_send_json_error('Error loading file: ' . $e->getMessage());
die();
}
}
I've verified that IOFactory::identify() and IOFactory::createReader() seem to be working, but when I call $reader->load() I am hitting a brick wall over and over.
The file is successfully being uploaded through $_FILES via the AJAX request
wp_handle_upload successfully handles the file and the file is visible in the wordpress uploads folder
Different spreadsheet files other than the testing file are returning the same error
Here's the error output:
Fatal error: Uncaught Error: Call to undefined method PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles::setWorkbookPalette()
in /home1/wp-content/plugins/tjg-csbs/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 566
Call stack:
PhpOffice\P\R\Xlsx::loadSpreadsheetFromFile()
wp-content/plugins/tjg-csbs/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php:166
PhpOffice\P\R\BaseReader::load()
wp-content/plugins/tjg-csbs/public/class-tjg-csbs-public.php:216
Tjg_Csbs_Public::tjg_csbs_ajax_get_spreadsheet_summary()
wp-content/plugins/tjg-csbs/public/class-tjg-csbs-public.php:186
Tjg_Csbs_Public::tjg_csbs_ajax_primary()
wp-includes/class-wp-hook.php:307
WP_Hook::apply_filters()
wp-includes/class-wp-hook.php:331
WP_Hook::do_action()
wp-includes/plugin.php:476
do_action()
wp-admin/admin-ajax.php:187
I've successfully used PHPSpreadsheet before with classic POST requests without encountering this error when not involving Javascript or AJAX in a different use case.
Any ideas where to check next to get this resolved? Huge thanks.
Related
I was trying to upload a video of size close to 50 MB using Azure's PHP SDK.
I ran into this error:
PHP Fatal error: Call to undefined method MicrosoftAzure\\Storage\\Blob\\Models\\CreateBlobOptions::getUseTransactionalMD5() in /var/www/<domain>/vendor/microsoft/azure-storage-blob/src/Blob/BlobRestProxy.php on line 1941
It only happens if I pass blob options to set correct mime type (video/mp4 in this case). If I upload the same video without setting blob options then it works just fine. Many other videos work fine even with the blob options set to video/mp4. The error is throwing me off.
Any guesses why it treats getUseTransactionalMD5 as an undefined method in this case?
Here is the minimal code
use MicrosoftAzure\Storage\Blob\BlobRestProxy;
use MicrosoftAzure\Storage\Common\Exceptions\ServiceException;
$connString = "DefaultEndpointsProtocol=http;AccountName=" . AZURE_ACCOUNTNAME . ";AccountKey=" . AZURE_KEY;
$blobRestProxy = BlobRestProxy::createBlobService($connString);
$content = fopen($file['tmp_name'], "r");
$contentType = "video/mp4";
$options = new CreateBlobOptions();
$options->setContentType($contenttype);
blobRestProxy->createBlockBlob("mycontainer", "myblob", $content, $options);
As mentioned in the comment, please change the following line of code:
$options = new CreateBlobOptions();
to
$options = new CreateBlockBlobOptions();
And that will fix the problem.
Essentially the reason you're getting this error is because of a breaking change in the SDK where they included the use of transaction MD5 in all upload/download methods. However, it was exposed in CreateBlockBlobOptions class through getUseTransactionalMD5() and not in CreateBlobOptions class. Because you're using latter instead of former, you're getting this error message.
Have tried the API call as listed on Podio dev site to upload a file and I am not getting much joy.
I am trying to "Upload a file" in the first instance using the POST operation and passing the json with the source url to the endpoint as specified.
I can use other methods just fine but since there is little in the way or error feedback I am stuck I keep getting error 404
I have used - https://developers.podio.com/doc/files/upload-file-1004361
(have tried both GET & POST)
image of method with error i get
Upload file method that you are trying to use (https://developers.podio.com/doc/files/upload-file-1004361) is expecting file path which is supposed to be local file but not url.
Here is example of how it should be used:
http://podio.github.io/podio-php/api-requests/
$file = PodioFile::upload($path_to_file, $filename_to_display);
print 'File uploaded. The file id is: '.$file->id;
Here is another example on how to work with files:
https://developers.podio.com/examples/files
I am developing a REST API using Laravel 5.1 that has use case as following: receive a base 64 decoded PDF, and return a workspace ID of a Document Management System (DMS) from the uploaded file. The DMS service that I use in this case is Alfresco.
Current Condition
The application succeed to receive base 64 string and decode it to a file. I store the decoded file into system temporary directory, and try to upload it to the Alfresco. I have previously built function that receive a file from a form request to be stored in the Alfresco, and it works. Here is the declaration and parameters stated in the function:
public static function uploadDocument(
$doc, // <-- Okay by form request, not okay by the API decoded file
$user, // credential
$password, // credential
$params = array() // array that contains ACE
)
{
However, when I tried to use the same function with different document source, it failed. By different document source, I mean the source comes from the decoded base 64, and can be seen as follow:
// Decrypt base64
$fileData = base64_decode($request->input('file'));
// Save the decoded file to a temp directory
$tmpDir = sys_get_temp_dir();
$fileName = $request->input("fileName");
$pdfFile = fopen("$tmpDir/$fileName", 'w');
fwrite ($pdfFile, $fileData);
// Upload the decrypted file to the Alfresco
$alfUsername = Config::get('alfresco.CMIS_BROWSER_USER');
$alfPassword = Config::get('alfresco.CMIS_BROWSER_PASSWORD');
$assignees = ['assignees' => []];
$alfObjId = Alfresco::uploadDocument(
$pdfFile,
$alfUsername,
$alfPassword,
$assignees
);
fclose ($pdfFile);
The Error
Call to a member function getClientOriginalName() on resource
That refers to this line:
$uniqueFileName = $alfresco
->getUniqueFileName([
'path' => $path,
'filename' => $doc->getClientOriginalName(), // <-- This line
'session' => $session
]);
Error screenshot
The Question
Can one uploads a decoded base 64 file to another service without using temporary file?
How can I convert the decoded file into a multipart form request or similar, in order that my upload function could consume?
Thank you.
Well, sure you can call other service without saving a temporary file. If the file is already in memory as a string you could use curl to send a new request sending the string as data. Using curl to create a request you could set the content type header to multipart form data
I'm using PHPExcel 1.7.8 to read .xls files, uploaded by a radom user. All is working properly with a valid .xls file, but now I wanted to make some tests with invalid files to check if the program displays good error messages.
So I took a .csv file, and renamed it with .xls (without converting anything, just changing the name) to the end, just to check...
Broken! :)
DOM ELEMENT: HTML
DOM ELEMENT: BODY
DOM ELEMENT: P
START OF PARAGRAPH:
END OF PARAGRAPH:
FLUSH CELL: A1 => block,date,hour...
array
1 =>
array
'A' => string 'block,date,hour...' (length=2777)
{"step":"error","errors":[],"warnings":[]}
Like you can see, there's an error message displaying, I didn't ask for that, and then the JSON that I usually write.
It happens on this line :
<?php
echo "Loading file\n";
try {
if (!($objPHPExcel = PHPExcel_IOFactory::load('path'))) {
echo "Failed\n";
return;
// ...
}
} catch(Exception $e) {
echo 'Exception !';
}
echo "Done\n";
And this code displays:
Loading file
/!\ ERROR MESSAGE ABOVE /!\
Done
My question is, is there a way with PHPExcel or anything else to check whether a file is a valid XLS file before I try to parse it?
Thank you.
Even if it's more than a year question, I still find it cumbersome to figure it out how to deal with this issue, I'll try to post my answer here.
If using try/catch block doesn't work (in my case, I renamed a jpg file to xls and the error handler doesn't work, instead of throwing error, invalid file just throws a warning), you can consider a manual checking using canRead() as Mark said, here's an example of how to use this function.
If you know what your filetypes are, you can define it manually and check against them:
$valid = false;
$types = array('Excel2007', 'Excel5');
foreach ($types as $type) {
$reader = PHPExcel_IOFactory::createReader($type);
if ($reader->canRead($file_path)) {
$valid = true;
break;
}
}
if ($valid) {
// TODO: load file
// e.g. PHPExcel_IOFactory::load($file_path)
} else {
// TODO: show error message
}
Hope this help anyone with the same problem.
Each reader in PHPExcel has a canRead() method that validates the file passed in to the read is of the appropriate format for that reader - the method returns a simple boolean True or False. A return of True from a call to the canRead() method of the PHPExcel_Reader_Excel5 class will confirm that the file can be read by that reader, irrespective of the file extension.
The IOFactory identify() method uses this call, testing against the Readers for each supported format in turn until it gets a true return from the canRead() call. The IOFactory load() method, in it's turn, uses identify() to determine which Reader should be used for the specified file.
The ability to verify a filetype (without depending on the file extension which can often be misleading) is particularly useful when you want to set additional arguments for the reader.
The fallback from identify()/load() is slightly less satisfactory: if canRead() returns false for all other Readers, then the file is treated as a CSV.
How can I prepare a dynamic image created by GD for upload?
I created a php script to create dynamic images based on the userid (EX: www.mywebsite.com/image/124.png <== that should show the user 124 info)
Now I need to upload it to Facebook with this script :
$photo_details = array(
'message'=> $message
);
$file = "$_GET[id].png";
$photo_details['image'] = '#/home/username/public_html/image/' . $file;
$upload_photo = $facebook->api('/'.$album_uid.'/photos', 'post', $photo_details);
When I use the upload script that way I get this error:
Fatal error: Uncaught CurlException: 26: failed creating formpost data
But If I uploaded 124.png to /image/ directory and and tried the same code again with using the ID 124 it works just fine. After a long research I came to conclusion the problem relay in the dynamic part since it works just fine with static images. How can I solve this problem?
Thank you so much for all the help.
Looks like the script tries to read the file directly from the filesystem instead of running the image generating script. You can solve this by setting $photo_details['image'] = 'http://www.mywebsite.com/image/'.$file; if Facebook class allows this kind of file opening.