I'm using Loopback4 to create a sort-of blog api. My posts model will contain an image (or perhaps several in the future).
What i'm trying to do is -> upload image when creating a new post.
I've read quite a few articles regarding this, but since i'm new to nodejs and loopback4 i'm having a bit of trouble making it work.
I've followed the answer written here Loopback 4: Upload multipart/form-data via POST method and i'm encountering some problems with it.
First: I'm using MySQL. Is there any way to save the image in the database? Or is it not a good practice? The work-around would be to upload the image and save only the image location in the DB.
Second: After following the tutorial and ending up with the code created i made a new post request for testing purposes. It looks something like this.
#post('/posts/upload', {
responses: {
'200': {
description: 'Post model instance',
content: { 'application/json': { schema: { type: 'object' } } },
},
},
})
async uploadFile(#requestBody({
description: 'multipart/form-data value.',
required: true,
content: {
[FORM_DATA]: {
schema: { 'media-type': Post },
},
},
})
body: unknown,
) {
return body;
}
That creates my post request in Swagger, but it shows like a big input box (text input). As far as i know swagger supports upload button. Is the content-type wrong? How could i test my upload function? I did something similar in NetCore2 and i had to convert my image to bytes (if i remember correctly), is the same problem here?
Any tips? Thanks!
Related
I am trying to use the Editor Component of Atlaskit to create a real time WYSIWYG editor however there is no proper documentation to get things done I am confused at the collabEdit part, React gives an error: cannot resolve CollabProvider, what exactly is this CollabProvider and how does it work ?
<Editor appearence="comment" collabEdit={{
useNativePlugin: true,
provider: Promise.resolve(
new CollabProvider(
{
url: 'http://localhost:3000',
securityProvider: () => ({
headers: {
Authorization: asapToken,
'user-ari': userId,
},
omitCredentials: true,
}),
docId: 24,
userId: 12,
},
pubSubClient,
),
),
inviteToEditHandler: this.inviteToEditHandler,
userId: 12,
isInviteToEditButtonSelected: true
}} />
In my experience you need to use Atlaskit editor + Prosemirror tweak + y-websocket: https://demos.yjs.dev/atlaskit/atlaskit.html. I'm still trying to figure out the whole thing by myself. I still don't understand how <img> elements should be enabled. See the source of demo at https://github.com/yjs/yjs-demos/tree/master/atlaskit.
Note that you need to modify the atlaskit.js in the demo to point to your own server
const provider = new WebsocketProvider('wss://demos.yjs.dev', 'atlaskit', ydoc)
The first argument is the y-websocket server and the another parameter is the channel name for the collaboration.
The method for persisting the y-websocket server data is still a bit unknown. See https://github.com/yjs/y-websocket/issues/14 for details about that. If you plan on running the y-websocket server on one machine and you're happy with simple file backed database, using y-leveldb might be enough.
I'm trying to perform a basic Laravel 5 post request which simply do the following:
Save some data into a database
Stores a file (image) into public storage under a name which is a possible combo of 20 random numbers following '.jpg'
Save a url (which is used to locate the image in an img tag. I'm aware this isn't the best approach so feel free to post)
However, when performing an ordinary post request with no special headers from angular 6 to laravel 5, for some reason the File keeps converting into an empty array. (Before and after shots are below)
Before:
0: Object { id: 0, body: null, file: File }
After:
0: Object { id: 0, body: null, file: [] }
The File is full and is used to create a preview on a canvas before submitting so It works. The console is logging this data the line before posting and returning the $req Request before performing any php code in Laravel.
So the only place anything could get lost in translation is the in between. Code is as follows:
Angular 6:
postToLaravel(object) {
console.log(object.message);
this.http.post(this.url + '/add/message', object).subscribe(res => {
console.log(res);
});
}
Laravel 5:
function addMessage(Request $req) {
return $req->messages;
The empty array keeps pushing nothing to storage under a name its registered as a jpg file but no image is shown.
On the component that images are uploaded we have the following block take place after a (change)="" event:
onFileSelected(e: any) {
this.sectedFile = e.target.files[0];
this.isImage = true;
this.messageService.addImage(this.id, this.sectedFile);
this.preview();
}
The service function just finds the right object and adds a file:
addImage(id, file) {
var index = this.data.findIndex(x => x['id'] == id);
this.data[index]['body'] = null;
this.data[index]['file'] = file;
}
And when the submit button is pressed it just takes all the variables in the service and compacts them into an object. this object contains messages which is an array of further objects (the objects are as shown at the top) (If that made sense)
pushMessageToServer() {
this.messageService.postToLaravel({
title: this.title,
location: this.location,
gender: this.gender,
age: this.age,
deadline: this.deadline,
messages: this.data
});
}
Is there something I'm missing here?
Let me know should You need any extra info.
Turns out images in FormData are passed through and displayed as empty objects in the console. I just needed to know how to grab them. Thanks for your help everyone
I'm trying to use pouchdb to save an image which has been encoded in base64 format as an attachment against a document (inline) and then retrieve it again.
However, when i retrieve the document it seems as though pouchdb has modified the base64 image data and has appended 'md5-' to it. There is also no 'data' attribute off of the attachment object, as i would have expected. Instead i find an object called 'digest'. What is this?
I have created an example:
var db = new PouchDB('example');
db.bulkDocs(
[
{
_id: '1',
name: 'example',
"_attachments": {
"avatar.jpg": {
"content_type": "image/jpg",
"data": [BASE65 DATA STRING]
}
}
],
function(err, response) {
if (!err) {
db.allDocs({ include_docs: true, attachments: true }, function(err, docs) {
var d = docs.rows[0].doc;
// d looks like this:
// {"name":"example","_attachments":{"avatar.jpg":{"content_type":"image/jpg","digest":"md5-57e396baedfe1a034590339082b9abce","stub":true}},"_id":"1","_rev":"1-ff23a959ae88b871b94374a784a07728"}
});
}
}
);
Full example can be found here: http://jsfiddle.net/ntan0ycL/
How would i go about retrieving the base64 representation of the image from the pouchdb document? I'm not sure if the problem lies in how i'm saving the attachment or how i'm retrieving it.
Thanks,
Andrew.
Looks like we made a mistake, and the allDocs() API doesn't support the attachments option. So what you're getting back is just an attachments stub.
I've filed an issue: https://github.com/pouchdb/pouchdb/issues/2771
In the meantime, you can use the normal getAttachment() or get() API with {attachments: true} to fetch the attachments individually. Sorry about that.
I am writing an app that uses a codeigniter backend custom REST service with a backbone front end. I am having trouble with creating a post(i.e. comment) in my db. I have read that enabling Backbone.emulateJSON() may be able to fix this. In summary I'm looking for where to include this line. A longer explanantion...
When I submit my form manually to create a new post the data is saved fine as expected. When I attempt the following in my postAddView...
save: function(e) {
e.preventDefault();
var that = this;
var postCollection = this.postCollection;
var newPost = {
message:"this is a post",
author_id:"22",
location:"New York"
}
postCollection.create(
newPost,
{
wait: true,
success: function(response){
console.log("successful" + response.toJSON);
},
error:function(err) {
console.log("this is the error "+ err.toJSON);
}
});
return this;
}
As as a result a new record is saved in my DB but no data is populated. Inspecting and comparing the networks in chrome shows that the ajax call from the backbone app submits it as 'request payload' vs. the form submission which is 'form data' (both are POSTS).
Based on my code above if anyone has any advice it would be much appreciated - however I'm also looking where to include backbone.emulateJSON() as many other posts have referenced this as a fix.
emulateJSON is not a function
Backbone.emulateJSON = true
http://backbonejs.org/#Sync-emulateJSON
I've used the webOS Ares tool to create a relatively simple App. It displays an image and underneath the image are two labels. One is static, and the other label should be updated with new information by tapping the image.
When I tap the image, I wish to obtain a JSON object via a URL (http://jonathanstark.com/card/api/latest). The typcial JSON that is returned looks like this:
{"balance":{"amount":"0","amount_formatted":"$0.00","balance_id":"28087","created_at":"2011-08-09T12:17:02-0700","message":"My balance is $0.00 as of Aug 9th at 3:17pm EDT (America\/New_York)"}}
I want to parse the JSON's "amount_formatted" field and assign the result to the dynamic label (called cardBalance in main-chrome.js). I know that the JSON should return a single object, per the API.
If that goes well, I will create an additional label and convert/assign the "created_at" field to an additional label, but I want to walk before I run.
I'm having some trouble using AJAX to get the JSON, parse the JSON, and assign a string to one of the labels.
After I get this working, I plan to see if I can load this result on the application's load instead of first requiring the user to tap.
So far, this is my code in the main-assistant.js file. jCard is the image.
Code:
function MainAssistant(argFromPusher) {}
MainAssistant.prototype = {
setup: function() {
Ares.setupSceneAssistant(this);
},
cleanup: function() {
Ares.cleanupSceneAssistant(this);
},
giveCoffeeTap: function(inSender, event) {
window.location = "http://jonathanstark.com/card/#give-a-coffee";
},
jcardImageTap: function(inSender, event) {
//get "amount_formatted" in JSON from http://jonathanstark.com/card/api/latest
//and assign it to the "updatedBalance" label.
// I need to use Ajax.Request here.
Mojo.Log.info("Requesting latest card balance from Jonathan's Card");
var balanceRequest = new Ajax.Request("http://jonathanstark.com/card/api/latest", {
method: 'get',
evalJSON: 'false',
onSuccess: this.balanceRequestSuccess.bind(this),
onFailure: this.balanceRequestFailure.bind(this)
});
//After I can get the balance working, also get "created_at", parse it, and reformat it in the local time prefs.
},
//Test
balanceRequestSuccess: function(balanceResponse) {
//Chrome says that the page is returning X-JSON.
balanceJSON = balanceResponse.headerJSON;
var balanceAmtFromWeb = balanceJSON.getElementsByTagName("amount_formatted");
Mojo.Log.info(balanceAmtFromWeb[0]);
//The label I wish to update is named "updatedBalance" in main-chrome.js
updatedBalance.label = balanceAmtFromWeb[0];
},
balanceRequestFailure: function(balanceResponse) {
Mojo.Log.info("Failed to get the card balance: " + balanceResponse.getAllHeaders());
Mojo.Log.info(balanceResponse.responseText);
Mojo.Controller.errorDialog("Failed to load the latest card balance.");
},
//End test
btnGiveCoffeeTap: function(inSender, event) {
window.location = "http://jonathanstark.com/card/#give-a-coffee";
}
};
Here is a screenshot of the application running in the Chrome browser:
In the browser, I get some additional errors that weren't present in the Ares log viewer:
XMLHttpRequest cannot load http://jonathanstark.com/card/api/latest. Origin https://ares.palm.com is not allowed by Access-Control-Allow-Origin.
and
Refused to get unsafe header "X-JSON"
Any assistance is appreciated.
Ajax is the right tool for the job. Since webOS comes packaged with the Prototype library, try using it's Ajax.Request function to do the job. To see some examples of it, you can check out the source code to a webOS app I wrote, Plogger, that accesses Blogger on webOS using Ajax calls. In particular, the source for my post-list-assistant is probably the cleanest to look at to get the idea.
Ajax is pretty much the way you want to get data, even if it sometimes feels like overkill, since it's one of the few ways you can get asynchronous behavior in JavaScript. Otherwise you'd end up with code that hangs the interface while waiting on a response from a server (JavaScript is single threaded).