I'm trying to backup and restore a sqlite database using flutter. The database file is backed up on a server via a php api; same for the restore.
The error returned
Unhandled Exception: DatabaseException(Error Domain=FMDatabase Code=26 "file is not a database" UserInfo={NSLocalizedDescription=file is not a database}) sql 'SELECT * FROM journal' args []
Here is my functions to backup on server and restore in the app
BACKUP FUNCTION
static exportDB(bool isWithMessage) async {
if(int.parse(Common.storage.read('user')['abonnement'])==1)
{
String path = await getDatabasesPath();
path += '/jonadatabase';
// Create an instance of GetConnect
final GetConnect _connect = GetConnect(
timeout: const Duration(seconds: 10),);
final FormData _formData = FormData({
'fichier': MultipartFile(File(path), filename: 'jonadatabase'),
'user_id': Common.storage.read('user')['id']
});
Map<String, String> headers = {
'Authorization': 'Bearer ${Common.storage.read('user')['token']}'
};
try {
final Response res = await _connect.post(
'${Common.apiLink}/fichier/${Common.storage.read('user')['id']}',
_formData, headers: headers);
if (res.body['status'].toString() == 'true') {
if (isWithMessage == true) {
Get.back();
Common.customSnackbar(
'Info', "DBExportSuccessfully".tr, Icons.check_circle,
CustomColor.primaryColor);
}
} else {
Get.back();
Common.customSnackbar(
'error'.tr, "errorWhenExportDB".tr, Icons.check_circle,
CustomColor.primaryColor);
}
} catch (err) {
// Handle errors
print(err);
}
}
else
{
if(isWithMessage == true) {
Common.customSnackbar(
'error'.tr, "upgradeToEverywherePlan".tr, Icons.info,
CustomColor.primaryColor, sec: 7);
Get.defaultDialog(title: '', content: Pricing(type: 'renew'));
}
}}
RESTORE FUNCTION
static loadDB() async {
var url = "${Common.webLink}/uploads/database/";
var filename = 'copy';
await Common.downloadFile(url, filename);
var dbPath = join(await getDatabasesPath(),'jonadatabase');
ByteData data = await rootBundle.load(join(await getDatabasesPath(), 'copy'));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(dbPath).writeAsBytes(bytes);
MainController.to.database = await openDatabase(dbPath);
if(Common.storage.hasData('user')) {
Common.storage.read('user')['fichier'] = 'copy';
}
}
Related
I have tested the API in Postman and the PDF renders fine. So I know the API is working correctly.
When I fetch the PDF from within my React code Adobe gives me the error: "Adobe Acrobat cannot open the because it is neither a supported file type or because the file has been damaged"
My React code:
const downloadFile = async uploadId => {
const response = await callFetch("/uploads/download/" + uploadId + "?officerId=" + officerId, "GET", "");
if (response.status === 401 || response.status === 403) {
alert("Error " + response.status);
sessionStorage.clear();
return;
}
const file = response.blob();
const url = URL.createObjectURL(
new Blob([file], {type:"application/pdf"})
);
const link = document.createElement('a');
link.href = url;
link.setAttribute(
'download',
`FileName.pdf`,
);
// Append to html link element page
document.body.appendChild(link);
// Start download
link.click();
// Clean up and remove the link
link.parentNode.removeChild(link);
URL.revokeObjectURL(url);
};
const callFetch = (endpoint, method, jsonStr) => {
let myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Accept","application/json");
return callFetchApi(endpoint, method, jsonStr, myHeaders);
};
const callFetchApi = (endpoint, method, data, myHeaders) => {
const serverName = "http://localhost:8080/AuxPolice/api";
myHeaders.append("Access-Control-Allow-Credentials", 'true');
myHeaders.append("Access-Control-Allow-Origin", '*');
const jwt = sessionStorage.getItem("jwt");
let headerJwt = "Bearer " + jwt;
if (jwt != null) {
myHeaders.append("Authorization", headerJwt);
}
let myInit = {method: method
,headers: myHeaders
};
let url = serverName + endpoint;
if (data) {
myInit.body = data;
}
let returnFetch = fetch(url, myInit);
return returnFetch;
};
Here is my Java code:
#GetMapping(value = "/download" + "/{id}")
public ResponseEntity<Resource> downloadGet(#PathVariable Long id, #RequestParam Long officerId) throws SQLException
{
Officer loggedInOfficer = this.auxPoliceService.getOfficer(officerId);
Upload paramRec = new Upload();
paramRec.setUploadId(id);
Upload download = auxPoliceService.getUploads(loggedInOfficer.getOfficerId(), paramRec).get(0);
Blob blob = download.getBlob();
byte [] bytes = blob.getBytes(1, (int)blob.length());
blob.free();
InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(bytes));
String filename = download.getFilename();
String contentType = "application/pdf; name=\"" + filename() + "\"";
HttpHeaders headers = new HttpHeaders();
headers.set("content-disposition", "inline; filename=" + filename);
return ResponseEntity.ok()
.headers(headers)
.contentLength(bytes.length)
.contentType(MediaType.parseMediaType(contentType))
.body(resource);
}
Any ideas?
I'm new to NodeJS where I'm trying to insert into a table with parameters so I can avoid SQL Injection and just escape any characters that might cause issues.
So I currently have an application that insert into the data without parameters.
Here is what I have so far:
var fs = require('fs');
var sql = require('mssql');
var LINQ = require("node-linq").LINQ;
const simpleParser = require('mailparser').simpleParser;
var Client = require('yapople').Client;
var client = new Client({
hostname: 'xxxxxx',
port: 995,
tls: true,
mailparser: true,
username: 'xxxxx',
password: 'xxxxx'
});
const config = {
user: 'xxxxxxx',
password: 'xxxxx',
server: 'xxxxx\\',
port: 'xxxxx'
database: 'xxxxxx',
options: {
instanceName: 'xxxxx'
}
};
(async function () {
try {
let pool = await sql.connect(config)
//Get all current emails
let emails = await pool.request()
.query('select uid from email')
//Get uids only
var uids = new LINQ(emails.recordset)
.Select(function(email) {return email.uid;})
.ToArray();
//Get all emails
client.connect(function() {
client.retrieveAll(function(err, messages) {
messages.forEach(function(message) {
//Check if the message exists in our database already.
var messageId = message.messageId;
var emailExists = new LINQ(uids)
.Where(x=>x == messageId).ToArray();
//If the message do not exists then add them to the database
if(emailExists.length == 0){
var sentDate = new Date(message.date).toISOString();
var subject = message.subject;
var body = message.text;
var mailAddress = "";
var mailAddressName = "";
if(message.from.length > 0){
mailAddress = message.from[0].address;
mailAddressName = message.from[0].name;
}
const request = pool.request();
request.input('uid', sql.VarChar, messageId);
request.input('mail_address', sql.VarChar, mailAddress);
request.input('mail_address_display_name', sql.VarChar, mailAddressName);
request.input('subject', sql.VarChar, subject);
request.input('body', sql.VarChar, body);
request.input('sent_date', sql.DateTime, sentDate);
request.input('created_by', sql.VarChar, 'system');
let result = await request.query('INSERT INTO email(uid, mail_address, mail_address_display_name, subject, body, sent_date, created_by) OUTPUT INSERTED.ID values (#uid, #mail_address, #mail_address_display_name, #subject, #body, #sent_date, #created_by)', (err, result) => {
console.dir(result)
})
}
});
client.quit();
})
});
} catch (err) {
console.log(err);
// ... error checks
}
})()
I was looking at prepared statements but I could not get that working.
Here is what I was attempting with prepared statements
const ps = new sql.PreparedStatement();
ps.input('uid', TYPES.VarChar);
ps.input('mail_address', TYPES.VarChar);
ps.input('mail_address_display_name', TYPES.VarChar);
ps.input('subject', TYPES.VarChar);
ps.input('body', TYPES.VarChar);
ps.input('sent_date', TYPES.DateTime);
ps.input('created_by', TYPES.VarChar);
ps.prepare('INSERT INTO email(uid, mail_address, mail_address_display_name, subject, body, sent_date, created_by) ' +
' OUTPUT INSERTED.email_id VALUES (#uid, #mail_address, #mail_address_display_name, #subject, #body, #sent_date, #created_by)',
err => {
ps.execute({
uid: messageId,
mail_address: mailAddress,
mail_address_display_name: mailAddressName,
subject: subject,
body: body,
sent_date: sentDate,
created_by: 'system'
}, (err, result) => {
// ... error checks
ps.unprepare(err => {
var x =1;
})
})
}
)
You can use the connection pool request object to add parameters, e.g.
const request = pool.request()
request.input('myval', sql.VarChar, 'value')
request.query('insert into testtable (somecolumn) values (#myval)', (err, result) => {
console.dir(result)
})
I have a complex object parameter that I need to send as post, as it could be too long for querystring. The post call is asking to have an excel file dynamically generated and then downloaded asynchronously. But all of this is happening inside of a react application. How does one do this using axios.post, react, and webapi? I have confirmed that the file does generate and the download up to the response does come back, but I'm not sure how to actually open the file. I have a hidden iframe that I'm trying to set the path, src, of the file to, but I dont know what response property to use.
// webapi
[HttpPost]
public HttpResponseMessage Post([FromBody]ExcelExportModel pModel)
{
var lFile = ProductDataModel.GetHoldingsExport(pModel);
var lResult = new HttpResponseMessage(HttpStatusCode.OK);
lResult.Content = new ByteArrayContent(lFile);
lResult.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "HoldingsGridExport.xls"
};
lResult.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return lResult;
}
// client side api
static getHoldingsExport({ UserConfigurationID, UserID, Configurations, ViewName, SortModel, FilterModel, UserConfigType, IsDefault, LastPortfolioSearchID = null, ProductId }) {
const filterModel = JSON.stringify(FilterModel); // saving as string as this model is dynamically generated by grid out of my control
const sortModel = JSON.stringify(SortModel);
let params = JSON.stringify({
UserConfigurationID,
UserID,
Configurations,
ViewName,
filterModel,
sortModel,
UserConfigType,
IsDefault,
LastPortfolioSearchID,
ProductId
});
return axiosInstance.post("/api/HoldingsExport", params);
}
// client side app call to get file
HoldingsApi.getHoldingsExport(config)
.then(function(response) {
debugger;
let test = response;
})
.catch(error => {
toastr.success('Failed to get export.');
});
This is how I've achieved file downloads by POSTing via Axios:
Axios.post("YOUR API URI", {
// include your additional POSTed data here
responseType: "blob"
}).then((response) => {
let blob = new Blob([response.data], { type: extractContentType(response) }),
downloadUrl = window.URL.createObjectURL(blob),
filename = "",
disposition = response.headers["content-disposition"];
if (disposition && disposition.indexOf("attachment") !== -1) {
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/,
matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, "");
}
}
let a = document.createElement("a");
if (typeof a.download === "undefined") {
window.location.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
}).catch((error) => {
// ...
});
Just in case the above solution does not serve you quite well, here is how I could be able to download videos that are hosted on S3 AWS buckets,
const handleDownload = () => {
const link = document.createElement("a");
link.target = "_blank";
link.download = "YOUR_FILE_NAME"
axios
.get(url, {
responseType: "blob",
})
.then((res) => {
link.href = URL.createObjectURL(
new Blob([res.data], { type: "video/mp4" })
);
link.click();
});
};
And I trigger handleDownload function in a button with onClick.
The url in the function has the video URL from S3 buckets
My Angular 1 application saves files to S3 and allows for a wide variety of files types.
When I retrieve the objects I use the following code:
export function show(req, res) {
const s3 = new aws.S3();
const s3Params = {
Bucket: S3_BUCKET,
Key: req.query.key + ''
};
res.attachment(req.query.key + '');
var fileStream = s3.getObject(s3Params).createReadStream();
fileStream.pipe(res);
}
I would like to open the received file on the client in a new window (just like on the AWS console) but I can't figure out how to go about it.
For example on the client side does not work at all:
.then(
(data) => {
var file = new Blob([data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
)
I really don't understand how the concept of data streams works.
If you don't have to download pdf, you may open it directly from s3.
s3client.getResourceUrl("your-bucket", "some-path/some-key.jpg");
This will return you url to the file.
So you need code like:
export function show(req, res) {
this.s3client = new aws.S3({
accessKeyId: options.accessKeyId,
secretAccessKey: options.secretAccessKey,
region: options.region
})
let resourceUrl = s3client.getResourceUrl(S3_BUCKET, req.query.key + '');
window.open(resourceUrl, '_blank');
}
I'm sorry, can't test it right now, but try. Should work.
All I had to do was get a signedUrl for the resource for this to work much simpler than what I was trying to do.
export function show(req, res) {
const s3 = new aws.S3();
const s3Params = {
Bucket: S3_BUCKET,
Key: req.query.key + ''
};
s3.getSignedUrl('getObject', s3Params, (err, data) => {
if (err) {
console.log(err);
return res.end();
}
const returnData = {
signedRequest: data,
};
res.write(JSON.stringify(returnData));
res.end();
});
}
and on the client all I have to do is open the link in a new tab:
openDoc(doc) {
this.$http()
.then(
(data) => {
this.$window.open(data.data.signedRequest, '_blank')
}
)
.catch(
(err) => {
this.Notification.error('failed to download attachment');
}
)
}
I am trying to use ng-file-upload to upload files using Angular. I need the byte array to store in our database (I cannot store the uploaded file on the server), but I also need the FormData as well. My problem is that I can only seem to get one or the other (either the byte array or the formdata) but not both.
Here is my Angular code:
$scope.uploadPic = function (file) {
$scope.emrDetailID = 7;
file.upload = Upload.upload({
url: '/SSQV4/SSQV5/api/Document/UploadEMRDocument',
method: 'POST',
data: { file: file, 'emrdetail': $scope.emrDetailID}
});
file.upload.then(function (response) {
$timeout(function () {
file.result = response.data;
$scope.imageID = file.result;
});
});
};
Using the code below, I can get the byte array and store it in my database:
public async Task<IHttpActionResult> UploadDocument()
{
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
var f = provider.Contents.First(); // assumes that the file is the only data
if (f != null)
{
string ClientIP = IPNetworking.GetIP4Address();
var filename = f.Headers.ContentDisposition.FileName.Trim('\"');
filename = Path.GetFileName(filename);
var extension = Path.GetExtension(filename).TrimStart('.');
var buffer = await f.ReadAsByteArrayAsync();
FileImageParameterModel pm = new FileImageParameterModel();
pm.binFileImage = buffer;
//pm.CompanyID = UserInfo.intMajorID;
pm.CompanyID = 10707;
pm.dteDocumentDate = Convert.ToDateTime("4/4/2016");
pm.dteExpiration = Convert.ToDateTime("4/4/2017");
pm.vchUserIP = ClientIP;
pm.vchUploadedbyUserName = UserInfo.Username;
pm.vchFileExtension = extension;
CommonClient = new CommonWebApiClient();
CommonClient.AuthorizationToken = UserInfo.AccessToken;
int imageID = await CommonClient.InsertNewFileImage(pm);
return Json(imageID);
}
else
{
return BadRequest("Attachment failed to upload");
}
}
Using the code below I can get the FormData
var provider = new MultipartFormDataStreamProvider(workingFolder);
await Request.Content.ReadAsMultipartAsync(provider);
var emr = provider.FormData["emrdetail"];
but then I can't get the byte array as using MultipartFormDataStreamProvider wants a folder to store the file.
There's got to be a way to get both. I have been searching the internet for 2 days and all I can find are the two solutions above neither of which solves my issue.
Any assistance is greatly appreciated!
You are thinking way to complicated. Here is some of my code which I used for file upload in AngularJS with .NET
Angular:
function uploadFileToUrl(file) {
var formData = new FormData(); // Notice the FormData!!!
formData.append('uploadedFile', file);
return $http({
url: uploadUrl,
method: 'POST',
data: formData,
headers: {
'Content-Type': undefined
}
}).then(resolve, reject);
function resolve(data) {
$log.debug('data : ', data);
return data;
}
function reject(e) {
$log.warn('error in uploadFileToUrl : ', e);
return $q.reject(e);
}
}
Server:
public Task HandleAsync([NotNull] UploadFilesCommand command)
{
return wrapper.InvokeOnChannel(async client =>
{
// init command
command.Output = new Dictionary<string, int>();
try
{
foreach (var file in command.Files)
{
var request = new UploadFileRequest
{
FileName = file.Name,
FileStream = file.Stream
};
UploadFileResponse response = await client.UploadFileAsync(request);
command.Output.Add(file.Name, response.Id);
}
}
finally
{
// dispose streams
foreach (var file in command.Files)
{
if (file.Stream != null)
{
file.Stream.Dispose();
}
}
}
});
}