I tried to add additional attachment to my document in PouchDB in my electron application. However I can only add last attachment and the old one is overwritten.
The following data is not amended in a way which add new file:
_attachments":{"someFile.jpg":{"content_type":"image/jpeg","revpos":5,"length":38718,"digest":"md5-X+MOUwdHmNeORSl6xdtZUg=="}
Should I read document first and recreate it adding additional file using multiple attachments with the following method:
db.put({
_id: 'mydoc',
_attachments: {
'myattachment1.txt': {
content_type: 'text/plain',
data: blob1
},
'myattachment2.txt': {
content_type: 'text/plain',
data: blob2
},
'myattachment3.txt': {
content_type: 'text/plain',
data: blob3
},
// etc.
}
});
?
Below you can see part of the code i try to run to check if i can add two attachments to one document (actually i try to use the same file twice to simplify test):
pdb.putAttachment(id, name, rev, file, type).then(function (result) {
console.log("att saved:");
console.log(result);
}).catch(function (err) {
console.log(err);
});
var newFileName = "new" + name;
pdb.putAttachment(id, newFileName, rev, file, type).then(function (result) {
console.log("att saved 2:");
console.log(result);
}).catch(function (err) {
console.log(err);
});
The outcome is:
Object {ok: true, id: "1489351796004", rev: "28-a4c41eff6fbdde8a722a920c9d5a1390"}
id
:
"1489351796004"
ok
:
true
rev
:
"28-a4c41eff6fbdde8a722a920c9d5a1390"
CustomPouchError {status: 409, name: "conflict", message: "Document update conflict", error: true, id: "1489351796004"}
error
:
true
id
:
"1489351796004"
message
:
"Document update conflict"
name
:
"conflict"
status
:
409
It looks I don't understand something or I do not know how to use putAttachment properly.
I would also add what how data in sqlite looks like(by-sequence table, json row):
{...,"_attachments":{"testPicture.jpg":{"content_type":"image/jpeg","revpos":34,"length":357677,"digest":"md5-Bjqd6RHsvlCsDkBKe0r7bg=="}}}
The problem here is how to add another attachment to the structure. Somehow I cannot achive that via putAttachment
Your question and especially the code are quite hard to read, so the error was not so easy to spot: You didn't wait for the promise to be resolved. When you update a document with revision 1, you have to wait for the results, read the revision from there, and only then write the second attachment. This would be my (untested) take on your code:
pdb.putAttachment(id, name, rev, file, type)
.then(function (result) {
// Use the new revision here:
return putAttachment(id, newFileName, result.rev, file, type);
}).then(function (result) {
console.log(result);
}).catch(function (err) {
console.log(err);
});
Adding two attachments at once is possible if you encode them correctly, but you're on your own with it. I'd recommend that you shouldn't do that – better use the abstractions that PouchDB provides.
Also don't analyze the underlying data structures too much, because depending on the storage adapter used the data storage might differ drastically. It's quite interesting how different adapters store their data, but never rely on anything you find out – data formats might change.
put replaces the document. If you want to add an attachment to an existing document without overwriting its contents you should use putAttachment.
Related
I am trying to convert a Word doc into a Google doc using the API via nodejs. The word docs are already in a folder and I just want to convert them into google docs. I am using v3.
The v3 docs say that in order to convert a file using copy you need to replace the convert parameter with the mimeType in the resource body.
I can't work out how to do that?
function listFiles(auth) {
const drive = google.drive({version: 'v3', auth});
drive.files.list({
q: "mimeType = 'application/msword'",
pageSize: 100,
fields: 'nextPageToken, files(id, name)',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const files = res.data.files;
if (files.length) {
console.log('Files:');
files.map((file) => {
console.log(`${file.name} (${file.id})`);
drive.files.copy({
fileId: file.id,
'name' : 'Updated File Name',
'mimeType' : 'application/vnd.google-apps.document'
})
});
} else {
console.log('No files found.');
}
});
}
Not sure that I am quite understanding how to reference the resource body. Would be grateful for a steer?
You want to convert Microsoft Word (doc files) to Google Document using the method of files.copy in Drive API v3.
You want to achieve this using googleapis with Node.js.
You have already been able to get and put files for Google Drive using Drive API.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
I think that drive.files.list() works in your script.
I think that drive.files.copy() has a modification part.
Please include name and mimeType in requestBody or resource.
In this case, it uses callback function for retrieving error message.
Modified script:
From:
drive.files.copy({
fileId: file.id,
'name' : 'Updated File Name',
'mimeType' : 'application/vnd.google-apps.document'
})
To:
drive.files.copy(
{
fileId: file.id,
requestBody: { // You can also use "resource" instead of "requestBody".
name: file.name,
mimeType: "application/vnd.google-apps.document"
}
},
(err, res) => {
if (err) return console.log("The API returned an error: " + err);
console.log(res.data); // If you need, you can see the information of copied file.
}
);
In this case, the filename of the DOC file is used by removing the extension. And the copied file is put to the same folder with the DOC file.
Note:
In this modified script, it suppose that the scopes you set can be used for using drive.files.copy(). If an error related to the scopes occurs, please add https://www.googleapis.com/auth/drive to the scopes.
References:
Files: copy
If I misunderstood your question and this was not the direction you want, I apologize.
I'm trying to update one of my subscriber's status using mailchimp API 3.0, Meteor and javascript.
Here is my js code I'm using:
request({
uri,
list_id,
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': 'apikey (my api key)'
},
json,
}, function(err, res, body) {
if (err) {
return console.log("err:", err);
}
console.log("connection succeed");
console.log("res: ", res.body);
console.log("body: ", body);
});
with
uri = "https://us15.api.mailchimp.com/3.0/lists/" + (id of my list) + "/members/" + (md5 of my user mail);
and
json = {
"email_address": (user mail as a string),
"status": "unsubscribed"
};
But I always have the same output:
I20181204-18:42:12.714(8)? title: 'Member Exists',
I20181204-18:42:12.714(8)? status: 400, I20181204-18:42:12.714(8)? detail: '(user mail adress) is already a list member. Use PUT
to insert or update list members.'
But I am using PUT already... The request works with POST if it's the first time I add the user. But now I can't update my user status...
Is something wrong with my request or with the way I use the API? Thanks in advance.
EDIT 1 -> trying with GET doesn't work. The request itself is correct but it has no effect on my subscriber's status. So I still need to make PUT work.
After looking at the official doc in the "Edit" tab, I found the answer!
The json required another mandatory parameter and should look like this:
json = {
"email_address": (user mail as a string),
"status_if_new": "unsubscribed",
"status": "unsubscribed"
};
I know that this is an older question but I just wanted to add something in the event that it helps someone.
I was having a similar issue intermittently with most of my PUT requests working as expected and some not.
It took me a while but eventually I figured out that some of my email addresses had spaces at the end.
This error would result.
Trimming the addresses before doing anything resolved my issue.
i am trying to send a pdf file using the url of the file and using the method "sendDocument", the problem is that i cant access the file directly because of the server where its stored. I tried to use the answer provided in this post:
readFileSync from an URL for Twitter media - node.js
It works, but the file is send as "file.doc". If i change the extension to pdf, it is the correct file. Is there any extra step i need to do to send the file with the correct name and extension, or is there another way i can achieve what i need?
EDIT: The code i am using to get the pdf looks exactly like the code in the anwser of the post i provided:
function getImage(url, callback) {
https.get(url, res => {
// Initialise an array
const bufs = [];
// Add the data to the buffer collection
res.on('data', function (chunk) {
bufs.push(chunk)
});
// This signifies the end of a request
res.on('end', function () {
// We can join all of the 'chunks' of the image together
const data = Buffer.concat(bufs);
// Then we can call our callback.
callback(null, data);
});
})
// Inform the callback of the error.
.on('error', callback);
}
To send the file i use something like this:
getImage(url, function(err, data){
if(err){
throw new Error(err);
}
bot.sendDocument(
msg.chat.id,
data,
);
})
Found the solution. I am using the telebot api (sorry for not mentionig that detail, but i did not knew it, i did not make the project).
I used the following line to send the file:
bot.sendDocument(chat_id, data, {fileName: 'file.pdf'});
You can specify the file name and file type by using this code:
const fileOptions = {
// Explicitly specify the file name.
filename: 'mypdf.pdf',
// Explicitly specify the MIME type.
contentType: 'application/pdf',
};
Full function:
getImage("https://your.url/yourfile.pdf", function(err, data){
if(err){
throw new Error(err);
}
const fileOptions = {
// Explicitly specify the file name.
filename: 'mypdf.pdf',
// Explicitly specify the MIME type.
contentType: 'application/pdf',
};
bot.sendDocument(msg.chat.id, data, {}, fileOptions);
});
NOTE: You MUST provide an empty object ({}) in place of Additional Telegram query options, if you have no query options to specify. For example,
// WRONG!
// 'fileOptions' will be taken as additional Telegram query options!!!
bot.sendAudio(chatId, data, fileOptions);
// RIGHT!
bot.sendAudio(chatId, data, {}, fileOptions);
More informations here:
https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
I'm tasked with modifying a legacy app so that users can upload payroll adjustments in bulk. Currently they have to fill out a form and input the data item by item, hitting submit after each one. I'm giving them the ability to upload a CSV file containing tons of adjustments at once.
On the server they are inserting items into couch one by one, like this:
function wsapiPOST(req, res, next) {
var path = req.path.substr(6)
, url = couchPath + path + requestUtil.buildQueryString(req);
request.post({
url: url,
headers: { 'content-type': 'application/json' },
body: JSON.stringify(req.body)
},function (err, resp, body) {
if (err) {
if (resp) {
res.writeHead(resp.statusCode);
res.end(body);
} else { // This would happen if the request timed out
res.writeHead(408);
res.end('timeout');
}
}
}).pipe(res);
}
The couch URL is built dynamically.
req.body contains the properties for a single item.
I'm new to couch but I'm not sure how to send multiple documents for insertion in a single operation. I could throw the request.post call into a loop as is, but I imagine that's not going to be very performant.
I just need pointed in the right direction for bulk insertion into couch via its REST API. Thanks!
You can use the bulk document API to insert (and even update) multiple documents.
You can use nano - there is a bulk insert option.
is there a way to identify binary messages from a server by tagging them with some kind of type attribute?
Background: I'm working with node.js and I'm sending binary messages to my client. At the moment these are only pictures sent as blobs. So on clientside I'm testing incoming messages with instance of Blob and then do something with the pics.
But now I additionally want to send other files like .txt over the websocket protocol (for downloads). I feel like this is much simpler than HTTP requests etc. But now I have to make a difference on incoming binary messages if they are images or textfiles or sth. else.
The Chrome Developertools show me that my incoming images (blobs) have a type attribute that is an empty string. As I read this attribute is read only, so I'm looking for a solution to identify my binary messages like I can do it with JSON Objects...
Thanks in advance for every idea :)
Edit:
Here is one example for sending images to the client. I'm using the "ws" module for nodejs.
fs.readFile(path, function (err, data)
{
if (!err)
{
connection.send(data, {binary: true}, function(err)
{
if (!err) console.log("Server finished sending image to client.");
else console.log("Error while sending imageto client.");
});
}
else console.log("Error while loading image");
});
Where could I add some kind of metadata to the binary data? Base64 encoding is no possibility for me.
If it's only about the format, you might use the content-type header to specify what kind of file type it is: text/plain or image/png or whatever you want to use ...
Of course, you can extend this idea and use a custom-header to transport any information you would like to transfer.
Or, which is the most flexible solution: Send back a real JSON object, embed all the metadata you need, and provide the binary content encoded within the JSON (using any encoding you like and that is compatible to JSON, such as Base64), such as:
{
"filename": "foo.txt",
"content-type": "image/png",
"binary-data": "A5EBC7FFEFDCD8975BC3..."
}
To use your code snippet as base, you might implement it as follows:
fs.readFile(path, function (err, data) {
if (err) { throw err; }
connection.send({
filename: 'foo.txt',
contentType: 'image/png',
data: JSON.stringify(data)
}, { binary: false }, function (err) {
if (err) { throw err; }
console.log('Server finished sending image to client.');
});
});
Please note that I did not test the code, but your final code should look somewhat similar to this one.
Hope this helps.