How to load files to local file system with vibed? - d

I need to send data from web-browser to local FS. For sending data I am using Vue-JS component
<file-upload class="my-file-uploader" name="myFile" id="myCustomId" action="/upload" multiple>Inside Slot Text</file-upload>
My server side based on vibed. But I can't find example how to save binary data to local FS.
router.any("/upload", &upload);
...
void upload(HTTPServerRequest req, HTTPServerResponse res)
{
}
It's seems that I should use HTTPServerRequest.files But I can't understand how to use it. User upload takes is multiple files.

You can find a lot of examples within the Vibe.d Github repository.
For example there's a small uploader.
router.post("/upload", &uploadFile);
...
void uploadFile(scope HTTPServerRequest req, scope HTTPServerResponse res)
{
auto pf = "file" in req.files;
enforce(pf !is null, "No file uploaded!");
try moveFile(pf.tempPath, Path(".") ~ pf.filename);
catch (Exception e) {
logWarn("Failed to move file to destination folder: %s", e.msg);
logInfo("Performing copy+delete instead.");
copyFile(pf.tempPath, Path(".") ~ pf.filename);
}
res.writeBody("File uploaded!", "text/plain");
}
I don't know much about Vue.js, but it seems they use file too.

Related

Accessing uploaded files from Camunda task

The final task of a Camunda process must write the files uploaded by the user to an specific folder. So, I've created the following 'Service task' as the last one of the process:
Then, from the Java project, I've added the FinishArchiveDelegate class with the following code:
package com.ower.abpar.agreements;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
public class FinishArchiveDelegate implements JavaDelegate {
#Override
public void execute(DelegateExecution execution) throws Exception {
System.out.println("Process finished: "+execution.getVariables());
}
}
When I check the logs, I see that I can see the document names, like:
document_1 => FileValueImpl [mimeType=image/jpeg, filename=Test_agreement1.jpg, type=file, isTransient=false]
The problem is that it only shows the file name and I'd need to request it from Camunda's database to copy it to another folder. Any suggestion or idea?
Thanks!
After some tests, I realized that I can get not only the name but all the uploaded files content using execution.getVariable(DOCUMENT_VARIABLE_NAME). So this is what I did:
// Get the uploaded file content
Object fileData = execution.getVariable("filename");
// The following returns a FileValueImpl object with metadata
// about the uploaded file, such as the name
FileValueImpl fileMetadata = FileValueImpl)execution.getVariableLocalTyped("filename")
// Set the destination file name
String destinationFileName = DEST_FOLDER + fileMetadata.getFilename();
...
// Create an InputStream from the file's content
InputStream in = (ByteArrayInputStream)fileData;
// Create an OutputStream to copy the data to the destination folder
OutputStream out = new FileOutputStream(destinationFileName);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Hope this helps someone, cheers!

Can I convert browser generated image blob to image file for upload?

I'm using fabric.js to dynamically create textures in Threes.js, and I need to save the textures to AWS. I'm using meteor-slingshot, which normally takes images passed in through a file selector input. Here's the uploader:
var uploader = new Slingshot.Upload("myFileUploads");
uploader.send(document.getElementById('input').files[0], function (error, downloadUrl) {
if (error) {
console.error('Error uploading', uploader.xhr.response);
alert (error);
}
else {
Meteor.users.update(Meteor.userId(), {$push: {"profile.files":downloadUrl}});
}
});
Uploading works fine from the drive ... but I'm generating my files in the browser, not getting them from the drive. Instead, they are generated from a canvas element with the following method:
generateTex: function(){
var canvTex = document.getElementById('texture-generator');
var canvImg = canvTex.toDataURL('image/jpeg');
var imageNew = document.createElement( 'img' );
imageNew.src = canvImg;
}
This works great as well. If I console.log the imageNew, I get my lovely image with base 64 encoding:
<img src=​"data:​image/​jpeg;​base64,/​9j/​
4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgID
//....carries on to 15k or so characters
If I console.log a file object added from the drive via filepicker ( not generated from a canvas ), I can see what the file object should look like:
file{
lastModified: 1384216556000
lastModifiedDate: Mon Nov 11 2013 16:35:56 GMT-0800 (PST)
name: "filename.png"
size: 3034
type: "image/png"
webkitRelativePath: ""
__proto__: File
}
But I can't create a file from the blob for upload, because there is no place in the file object to add the actual data.
To sum up I can:
Generate an image blob and display it in a dom element
Upload files from the drive using meteor-slingshot
inspect the existing file object
But I don't know how to convert the blob into a named file, so I can pass it to the uploader.
I don't want to download the image, (there are answers for that), I want to upload it. There is a "chrome only" way to do this with the filesystem API but I need something cross browser (and eventually cross platform). If someone could help me with this, I would have uncontainable joy.
Slingshot supports blobs just as well as files: https://github.com/CulturalMe/meteor-slingshot/issues/22
So when you have a canvas object called canvTex and a Slingshot.Upload instance called uploader, then uploading the canvas image is as easy as:
canvTex.toBlob(function (blob) {
uploader.send(blob, function (error, downloadUrl) {
//...
});
});
Because blobs have no names, you must take that into account when defining your directive. Do not attempt to generate a key based on the name of the file.

How to use Mongoose(a http server) to serve different request?

I am a newbie in http and I am using a embedded http server called mongoose.
Using a web root in ~/web_root, I would like to do :
if uri == "/hello"
show "hello world"
else
show the file in web_root like index.html
I tried to use mongoose like this
struct mg_server *server;
server = mg_create_server(p, HttpEventHandler);
mg_set_option(server, "document_root", "~/web_root");
mg_set_option(server, "listening_port", "8080");
for(;;)
mg_poll_server(server, 1000);
and this is HttpEvenHandler
int HttpEventHandler(struct mg_connection *conn, mg_event ev) {
if(ev == MG_AUTH)
return MG_TRUE;
else if(ev == MG_REQUEST) {
if(strcmp("/hello", conn->uri) == 0) {
mg_printf_data(conn, "%s\n", "hello world");
}
return MG_TRUE;
}
// I don't know what to write here
return MG_FALSE;
}
else if(ev == MG_REQUEST) {
if(strcmp("/hello", conn->uri) == 0) {
mg_printf_data(conn, "%s\n", "hello world");
return MG_TRUE;
}
return MG_FALSE; // Let Mongoose serve the request
}
Also, I don't think that is going to work:
mg_set_option(server, "document_root", "~/web_root");
Specify a full path, e.g. /home/joe/web_root.
Is that REALLY what you want to achieve?
The document states that you can configure what kind of URIs are recognized as CGI invocation by command line options like -cgi_pattern /cgi-bin/*.cgi.
Then you only need to put a CGI executable named hello which outputs "hello world" under ~/web_root and tell the Mongoose server to use it as the only possible CGI: -cgi_pattern /hello$ (I haven't tested it by myself, though)
Hm, it seems that mg_set_option() is nowhere to find any more (ver. 7.3).
The correct API call for setting the web root directory would be: mg_http_serve_dir( connection, http_event_object, options);
The last parameter "options" has a member mg_http_serve_opts::root_dir. That would be the way to specify the web root directory for serving.
From design point of view this recent approach is more flexible, allowing to serve different directories based on different endpoints.

Create a text file in Google Glass

I am able to install native apps in Google Glass now. I hope to know how to create a text file using native apps in Google Glass so that I can save data to text files.
Thanks!
Since Glass is an Android device and you are writing native Android apps for it, you should be able to write text files like you would on any other Android device.
The Android documentation on data storage should be helpful.
I tried the following code to create a file in Google Glass. The following code works with Android, which has a sd card. But does not work for Google Glass. Does anyone know how to create a text file in the Glass? Thanks!
public void SaveSubjectID(String filename, Context ctx) {
try {
//Find the directory for the SD Card using the API
//*Don't* hardcode "/sdcard"
// Toast.makeText(getBaseContext(), "files", Toast.LENGTH_SHORT).show();
//create a folder in a app.
//http://stackoverflow.com/questions/6911041/how-to-​create-folder-into-sd-card-in-android
File rootDirect = new File(Environment.getExternalStorageDirectory() + "/SmartTexting");
if(!rootDirect.exists())
{ rootDirect.mkdir() ;
}
File subjectDirect = new File(Environment.getExternalStorageDirectory() + "/SmartTexting/"+"subject");
if(!subjectDirect.exists())
{ subjectDirect.mkdir() ;
}
//File sdcard = Environment.getExternalStorageDirectory();
File file = new File(subjectDirect,filename);
// Toast.makeText(getBaseContext(), "files created", Toast.LENGTH_SHORT).show();
FileOutputStream fos2 = new FileOutputStream(file, true);
String outline = "test"
+ "\n";
fos2.write(outline.getBytes());
fos2.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I hope you have found out the correct answer by now, still this answer goes for all those who haven't found yet.
Code for writing file to google glass:
try {
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File f = new File(path,"file_new.txt");
f.createNewFile();
Log.d("file pathhhh", "result"+f.getAbsolutePath());
Log.d("file created", "result"+f.createNewFile());
FileOutputStream fOut = new FileOutputStream(f);
//FileOutputStream fileout=openFileOutput(f);
OutputStreamWriter outputWriter=new OutputStreamWriter(fOut);
//writer = new FileWriter(file1);
//writer.write(text.toString());
outputWriter.write(text.toString());
/** Closing the writer object */
outputWriter.close();
Log.d("success", "success"+Environment.getExternalStorageState()+Environment.getStorageState(path));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The key is to write file in DCIM folder and dont expect the file will be created then only.
To see whether the file has been created or not, shut down the glass and power it on again, you will find the new file in the DCIM folder

Why does WebSharingAppDemo-CEProviderEndToEnd sample still need a client db connection after scope creation to perform sync

I'm researching a way to build an n-tierd sync solution. From the WebSharingAppDemo-CEProviderEndToEnd sample it seems almost feasable however for some reason, the app will only sync if the client has a live SQL db connection. Can some one explain what I'm missing and how to sync without exposing SQL to the internet?
The problem I'm experiencing is that when I provide a Relational sync provider that has an open SQL connection from the client, then it works fine but when I provide a Relational sync provider that has a closed but configured connection string, as in the example, I get an error from the WCF stating that the server did not receive the batch file. So what am I doing wrong?
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = hostName;
builder.IntegratedSecurity = true;
builder.InitialCatalog = "mydbname";
builder.ConnectTimeout = 1;
provider.Connection = new SqlConnection(builder.ToString());
// provider.Connection.Open(); **** un-commenting this causes the code to work**
//create anew scope description and add the appropriate tables to this scope
DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription(SyncUtils.ScopeName);
//class to be used to provision the scope defined above
SqlSyncScopeProvisioning serverConfig = new SqlSyncScopeProvisioning();
....
The error I get occurs in this part of the WCF code:
public SyncSessionStatistics ApplyChanges(ConflictResolutionPolicy resolutionPolicy, ChangeBatch sourceChanges, object changeData)
{
Log("ProcessChangeBatch: {0}", this.peerProvider.Connection.ConnectionString);
DbSyncContext dataRetriever = changeData as DbSyncContext;
if (dataRetriever != null && dataRetriever.IsDataBatched)
{
string remotePeerId = dataRetriever.MadeWithKnowledge.ReplicaId.ToString();
//Data is batched. The client should have uploaded this file to us prior to calling ApplyChanges.
//So look for it.
//The Id would be the DbSyncContext.BatchFileName which is just the batch file name without the complete path
string localBatchFileName = null;
if (!this.batchIdToFileMapper.TryGetValue(dataRetriever.BatchFileName, out localBatchFileName))
{
//Service has not received this file. Throw exception
throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("No batch file uploaded for id " + dataRetriever.BatchFileName, null));
}
dataRetriever.BatchFileName = localBatchFileName;
}
Any ideas?
For the Batch file not available issue, remove the IsOneWay=true setting from IRelationalSyncContract.UploadBatchFile. When the Batch file size is big, ApplyChanges will be called even before fully completing the previous UploadBatchfile.
// Replace
[OperationContract(IsOneWay = true)]
// with
[OperationContract]
void UploadBatchFile(string batchFileid, byte[] batchFile, string remotePeer1
I suppose it's simply a stupid example. It exposes "some" technique but assumes you have to arrange it in proper order by yourself.
http://msdn.microsoft.com/en-us/library/cc807255.aspx