WordPress - ERR_BAD_RESPONSE admin-ajax-php file upload - javascript

I'm trying to upload files in WordPress using admin-ajax.php
I have this code in my functions.php file
function upload_docs(){
var_dump($_FILES);
}
add_action('wp_ajax_nopriv_upload_docs', 'upload_docs');
add_action('wp_ajax_upload_docs', 'upload_docs');
The function at the moment is a test that I want to use to debug what information is passed from the front-end which is a Vue app hosted in a page template.
I've correctly loaded and localized the Vue CSS and js files and after the build, in my localhost, I'm able to pass the other forms I have configured on my functions file
On the front-end side, the Vue app has this method that will add the needed information to the WordPress backend
sendUploadForm(){
let documents = this.$refs.uploadedFiles.files
let userData = new FormData()
for(let i = 0; i < documents.length; i++ ){
userData.append('file[]', documents[i])
}
userData.append('action', 'upload_docs')
axios.post(wp_param.ajaxurl, userData).then( res => {
console.log(res)
}).catch( e => console.log(e) )
}
What is going wrong with the code? I will always get a 500 error status code ERR_BAD_RESPONSE and I don't know if the function is called because I'm unable to see any var_dump or var_export from PHP. I've tried to enable the debug in wp-config file but nothing changed.
Any suggestion?

Add these additional two lines under your WP_DEBUG one, make the error happen again, and check in the folder wp-content/ if you see a new file debug.log.
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Consider:
Implementing nonces and permission checks to protect your endpoints
If only logged in users are supposed to be able to upload files, ensure the no_priv method is properly locked down
Using a custom REST API endpoint instead of admin-ajax https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
Terminate your function with wp_die(); when using AJAX in WordPress

I was stuck with this problem because of WordPress plugin conflicts.
You can disable unused plugins and check.

Related

How to read text file from filesystem in JavaScript

I have tried different approaches to read a text file from the local file system in JavaScript and display the content of the file in alert() but all to no avail.
Approach 1
function readTextFile(file) {
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file , false);
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4) {
if (rawFile.status === 200 || rawFile.status == 0) {
var allText = rawFile.response;
document.getElementById("content").innerText = allText;
alert(allText);
}
} else {
alert("Can't read the file");
}
}
rawFile.send(null);
}
readTextFile("FormulaQuestion.txt");
The FormulaQuestion.txt file is in the same directory with the html file, this approach shows an empty alert window on the browser
Approach 2 using fetch method
fetch('FormulaQuestion.txt')
.then(response => response.text())
.then((data) => {
alert(data);
})
This doesn't show anything
Approach 3 using JQuery
$.get('FormulaQuestion.txt', function (data) {
alert(data)
}, 'text');
This doesn't work either.
I am building a desktop application that uses a web browser control to load html file which is embedded into the application. The application reads the string from sqlite database and save it in the FormulaQuestion.txt file, then refreshes the WebControl component which reloads the html file.
Now when the html file is reloaded, the JavaScript should read the text file and display it on alert() which once the alert is able to display the file content, i will then set it to a paragraph and remove the alert().
Please someone should help me out.
Browsers by design do not allow access to the file system for JavaScript, as allowing such access would be a serious security concern.
To provide the FormulaQuestion.txt file to your script you will need to host the file on a server and request it via a HTTP request (like with your fetch). The key thing here is that a server is needed to actually transmit the file over the HTTP protocol to your script.
If working locally, there are many options for running a local server.
The npm serve module,
Wamp
Apache
You may also want to try out some free tier services like Vercel or Netlify. Both I believe allow you to just drag/drop a file and it will host it for you.

Does 'onDidChangeTextDocument()' promise in VScode extension depend on the user's active window to start listening?

I'm a new developer and this is my first Stack Overflow post. I've tried to stick to the format as best as possible. It's a difficult issue for me to explain, so please let me know if there's any problems with this post!
Problem
I'm working on a vscode extension specifically built for Next.js applications and running into issues on an event listener for the onDidChangeText() method. I'm looking to capture data from a JSON file that will always be located in the root of the project (this is automatically generated/updated on each refresh of the test node server for the Next.js app).
Expected Results
The extension is able to look for updates on the file using onDidChangeText(). However, the issue I'm facing is on the initial run of the application. In order for the extension to start listening for changes to the JSON file, the user has to be in the JSON file. It's supposed to work no matter what file the user has opened in vscode. After the user visits the JSON file while the extension is on, it begins to work from every file in the Next.js project folder.
Reproducing this issue is difficult because it requires an extension, npm package, and a next.js demo app, but the general steps are below. If needed, I can provide code for the rest.
1. Start debug session
2. Open Next.js application
3. Run application in node dev
4. Do not open the root JSON file
What I've Tried
Console logs show we are not entering the onDidTextDocumentChange() block until the user opens the root JSON file.
File path to the root folder is correctly generated at all times, and prior to the promise being reached.
Is this potentially an async issue? Or is the method somehow dependent on the Active Window of the user to start looking for changes to that document?
Since the file is both created and updated automatically, we've tested for both, and neither are working until the user opens the root JSON file in their vscode.
Relevant code snippet (this will not work alone but I can provide the rest of the code if necessary. ).
export async function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "Next Step" is now active!');
setupExtension();
const output = vscode.window.createOutputChannel('METRICS');
// this is getting the application's root folder filepath string from its uri
if (!vscode.workspace.workspaceFolders) {
return;
}
const rootFolderPath = vscode.workspace.workspaceFolders[0].uri.path;
// const vscode.workspace.workspaceFolders: readonly vscode.WorkspaceFolder[] | undefined;
// this gives us the fileName - we join the root folder URI with the file we are looking for, which is metrics.json
const fileName = path.join(rootFolderPath, '/metrics.json');
const generateMetrics = vscode.commands.registerCommand(
'extension.generateMetrics',
async () => {
console.log('Succesfully entered registerCommand');
toggle = true;
vscode.workspace.onDidChangeTextDocument(async (e) => {
if (toggle) {
console.log('Succesfully entered onDidChangeTextDocument');
if (e.document.uri.path === fileName) {
// name the command to be called on any file in the application
// this parses our fileName to an URI - we need to do this for when we run openTextDocument below
const fileUri = vscode.Uri.parse(fileName);
// open the file at the Uri path and get the text
const metricData = await vscode.workspace
.openTextDocument(fileUri)
.then((document) => {
return document.getText();
});
}
}
});
});
}
Solved this by adding an "openTextDocument" call inside the "registerCommand" block outside of the "onDidChangeTextDocument" function. This made the extension aware of the 'metrics.json' file without it being open in the user's IDE.

Upload file to Google Drive with React and Google App script

I am trying to upload file with Google App script and React.
Google Script:
function uploadArquivoParaDrive(base64Data, nomeArq, idPasta) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(nomeArq);
var file = DriveApp.getFolderById(idPasta).createFile(ss);
return file.getName();
}catch(e){
return 'Erro: ' + e.toString();
}
}
I can run this ant it works:
function uploadFile() {
var image = UrlFetchApp.fetch('url to some image').getBlob();
var file = {
title: 'google_logo.png',
mimeType: 'image/png'
};
file = Drive.Files.insert(file, image);
Logger.log('ID: %s, File size (bytes): %s', file.id, file.fileSize);
}
This is React script:
onSubmit = (e) => {
e.preventDefault();
axios.get(url, {...this.state}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}, (response) => {
console.log(response);
})
};
setFile = (event) => {
console.log(event.target.files)
this.setState({file: event.target.files[0]});
};
render() {
return (
<form>
<input type="file" id="file" onChange={this.setFile} />
<button onClick={this.onSubmit}>ADD</button>
</form>
)
}
I am trying with POST, but I am getting 400 response. I know that this can't be GET request, but and with it, I am getting - 200 with no response.
I can insert rows in sheets, but I want to upload files to Google Drive with Google App Scripts.
I know that there is a way to upload files via Google Scripts and React, because, there is a way without React (google.script.run).
Here are two different approaches that are used in mixed mode. It's unacceptable in some contexts.
Let's say softly 'React is a dummy'. This is an add-on that you should always avoid when somewhat comes to something that you depend on, but you cannot change. See what SOLID is.
Below it is always assumed that you are working in a browser. Your web-pages are hosted in the web application of the Google Apps Script.
The first approach. Using XMLHttpRequests
On client side you have to use XMLHttpRequests call from your browser.
On server side you have to use doGet doPost reserved functions. Always transfer data in a clear and simple format. This will save time searching for errors.
Example https://stackoverflow.com/a/11300412/1393023
The second approach. Using Client-side API
On client side you have to use google.script.run call from your browser.
On server side you have to use your functions. Always transfer data in a clear and simple format. This will save time searching for errors.
Example https://stackoverflow.com/a/15790713/1393023
Consequence
Your example has signs of mixing approaches. Unfortunately, it cannot be quickly debugged.
There is no reason that React is causing the problem. If so, then your architecture is incorrect.
If you want to use axios, then you need to consider the first approach.
If you want to use google.script.run then you need to catch onSubmit then you need to call an interface that implement google.script.run. Usually asynchronously, since the last call will still be completed with a callback.

How to read a file being saved to Parse server with Cloud Code, before actually saving it?

I'm trying to use Cloud Code to check whether a user-submitted image is in a supported file type and not too big.
I know I need to do this verification server-side and I think I should do it with Cloud Code using beforeSave – the doc even has a specific example about data validation, but it doesn't explain how to handle files and I couldn't figure it out.
I've tried the documented method for saving files, ie.
file = fileUploadControl.files[0];
var parseFile = new Parse.File(name, file);
currentUser.set("picture", parseFile);
currentUser.save();
and in the Cloud Code,
Parse.Cloud.beforeSave(Parse.User, (request, response) => { // code here });
But 1. this still actually saves the file on my server, right? I want to check the file size first to avoid saving too many big files...
And 2. Even then, I don't know what to do in the beforeSave callback. It seems I can only access the URL of the saved image (proof that it has been uploaded), and it seems very counter-intuitive to have to do another https request to check the file size and type before deciding whether to proceed with attaching the file to the User object.
(I'm currently using remote-file-size and file-type to check the size and type of the uploaded file, but no success here either).
I also tried calling a Cloud function, but it feels like I'm not doing the right thing, and besides I'm running into the same issues.
I can call a Cloud function and pass a saved ParseFile as a parameter, and then I know how to save it to the User object from the Cloud Code using the masterkey, but as above it still involves uploading the file to the server and then re-fetching it using its URL.
Am I missing anything here?
Is there no way to do something like a beforeSave on Parse.File, and then stop the file from being saved if it doesn't meet certain criteria?
Cheers.
If you have to do something with files, parse lets you overwrite the file adapter to handle file operations.
You can indicate the file adapter to use in your ParseServer instatiation:
var FSStoreAdapter = require('./file_adapter');
var api = new ParseServer({
databaseURI: databaseUri ,
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID,
filesAdapter: fs_store_adapter, // YOUR FILE ADAPTER
masterKey: process.env.MASTER_KEY, //Add your master key here. Keep it secret!
serverURL: "https://yourUrl", // Don't forget to change to https if needed
publicServerURL: "https://yourUrl",
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query subscriptions
}
maxUploadSize: "500mb" //you will now have 500mb limit :)
});
That said, you can also specify a maxUploadSize in your instatiation as you can see in the last line.
you have to use save in background
file = ParseFile("filename", file)
file?.saveInBackground({ e ->
if (e == null) {
} else {
Toast.makeText(applicationContext, "Error: $e", Toast.LENGTH_SHORT).show()
e.printStackTrace()
Log.d("DEBUG", "file " + e.code)
}
}, { percentDone ->
Log.d("DEBUG", "file:" + percentDone!!)
})

ASP.net Rejuicer combine js dynamically

Im looking at using Rejuicer http://rejuice.me/ to combine all the JS files of my ASP.net MVC site into one JS file. This works ok but it doesnt allow me to add or remove JS files without having to also reset/recycle the application, as all the configuration is set in the Application_Start() event handler.
Does anyone have any ideas on how I can get around this. Or if there is a better alternative to Rejuicer?
Loading configuration in Application_Start is a trade off. Other option is to hook into FileSystemWatcher and wait for folder changes. Given the nature of a web application, this isn't ideal. Some alternative use web.config which also forces a reset.
There are tools like Workbench which does its thing during development (in VS.NET). This removes dependency on the application start cycle and files are there when the app starts up.
In the _layout.cshtml file I have code similar to this. The list of js files for the site can be defined here without having to reset or recompile the site.
#{
//combine all JS files into one file using Rejuicer.
List<string> JsFiles = new List<string>();
//define list of JS files here
JsFiles.Add("~/Scripts/One.js");
JsFiles.Add("~/Scripts/Two.js");
if (System.Web.HttpContext.Current.Application["JsFileListing"] != null)
{
var JsFileRejuiced = (List<string>)System.Web.HttpContext.Current.Application["JsFileListing"];
//check if we have any new/removed/renamed files
if (JsFiles.Except(JsFileRejuiced).Count()> 0 || JsFileRejuiced.Except(JsFiles).Count() > 0)
{
//force application reset
HttpRuntime.UnloadAppDomain();
}
}
if (System.Web.HttpContext.Current.Application["JsFileListing"] == null)
{
var Combiner = Rejuicer.OnRequest.ForJs("~/Combined.js").Combine;
foreach (var file in JsFiles)
{
Combiner.File(file);
}
Combiner.Configure();
System.Web.HttpContext.Current.Application["JsFileListing"] = JsFiles;
}
}
#Rejuicer.Rejuiced.JsFor("~/Combined.js")

Categories

Resources