Google Forms uploaded file is stored two times in gDrive - file-upload

I have a Google Form with 3 fields and 1 upload file field, which is linked to a Google spreadsheet.
Every time I submit the form, my attachment is stored twice in my gDrive folders, one is in the root folder (the original file), and the other one is in the right Form_Name (File Responses), the renamed file (see script).
Both the Google Form and the Responses are inside a shared folder.
I have a script running on form submit (with a trigger) which renames the file before saving it, using some of the other submitted fields, tho only the one in Form_Name (File Responses) is renamed.
My need is to only keep the renamed file and delete the one in my gDrive root folder.
This is my script.
function onFormSubmit(e){
var form = FormApp.getActiveForm();
var formResponses = form.getResponses();
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
switch(itemResponse.getItem().getTitle()){
case "Time":
var timeString = itemResponse.getResponse();
break;
case "Author":
var authorString = "_" + itemResponse.getResponse();
break;
case "Type":
var typeString = "_" + itemResponse.getResponse();
break;
case "Setup.ini file":
var fileId = itemResponse.getResponse();
break;
}
}
var fileNameString = timeString + typeString + authorString;
Logger.log('renameFile('+fileId+','+fileNameString+');');
console.log('renameFile('+fileId+','+fileNameString+');');
renameFile(fileId,fileNameString);
}
function renameFile(id,fileName) {
var file = DriveApp.getFileById(id);
file.setName(fileName);
}

Working code! Thanks to this thread found by Tanaike -> stackoverflow.com/q/56171896
function onFormSubmit(e){
var form = FormApp.getActiveForm();
var formResponses = form.getResponses();
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
switch(itemResponse.getItem().getTitle()){
case "Time":
var timeString = itemResponse.getResponse();
break;
case "Author":
var authorString = "_" + itemResponse.getResponse();
break;
case "Stint":
var typeString = "_" + itemResponse.getResponse();
break;
case "Setup.ini file":
var fileId = itemResponse.getResponse();
var uploadedFile = DriveApp.getFileById(fileId);
var uploadedFileName = uploadedFile.getName();
break;
}
}
var fileNameString = timeString + typeString + authorString;
Logger.log('renameFile('+fileId+','+fileNameString+');');
Logger.log('thrashRootFile('+uploadedFileName+');');
console.log('renameFile('+fileId+','+fileNameString+');');
console.log('thrashRootFile('+uploadedFileName+');');
renameFile(fileId,fileNameString);
thrashRootFile(uploadedFileName);
}
function renameFile(id,fileName) {
var file = DriveApp.getFileById(id);
file.setName(fileName);
}
function thrashRootFile(fileName){
var p1 = fileName.split(" - ");
var extension = p1[p1.length - 1];
p1.pop();
var name = p1.join(" - ");
var p2 = "";
if (extension.indexOf(".") > -1) {
p2 = "." + extension.split(".")[1];
}
var orgFilename = name + p2;
// Move uploaded file to the trash.
var orgFiles = DriveApp.getRootFolder().getFilesByName(orgFilename);
if (orgFiles.hasNext()) {
var orgFile = orgFiles.next();
orgFile.setTrashed(true);
}
}

Related

Error when uploading file using Microsoft Graph API

I am trying to upload a large file to One Drive using Microsoft Graph API.
Uploading to One Drive works normally, but the file is damaged.
Please help me to solve the problem.
public ActionResult UploadLargeFiles(string id, [FromForm]IFormFile files)
{
string fileName = files.FileName;
int fileSize = Convert.ToInt32(files.Length);
var uploadProvider = new JObject();
var res = new JArray();
var isExistence = _mailService.GetUploadFolder(id);
if (isExistence != HttpStatusCode.OK)
{
var createFolder = _mailService.CreateUploadFolder(id);
if (createFolder != HttpStatusCode.Created)
{
return BadRequest(ModelState);
}
}
if (files.Length > 0)
{
var uploadSessionUrl = _mailService.CreateUploadSession(id, fileName);
if (uploadSessionUrl != null)
{
if (fileSize < 4194304)
{
uploadProvider = _mailService.UploadByteFile(id, uploadSessionUrl, files);
res.Add(uploadProvider);
}
}
else
{
return BadRequest(ModelState);
}
}
return Ok();
}
createUploadSession
public string CreateUploadSession(string upn, string fileName)
{
var uploadSession = _mailGraphService.CreateUploadSession(upn, fileName).Result;
var sessionResult = new UploadSessionDTO(uploadSession);
return sessionResult.uploadUrl;
}
public async Task<UploadSessionDTO> CreateUploadSession(string upn, string fileName)
{
this.InitHttpClient();
var jObject = JObject.FromObject(new { item = new Dictionary<string, object> { { "#microsoft.graph.conflictBehavior", "rename" } }, fileSystemInfo = new Dictionary<string, object> { { "#odata.type", "microsoft.graph.fileSystemInfo" } }, name = fileName });
var toJson = JsonConvert.SerializeObject(jObject);
var content = new StringContent(toJson, Encoding.UTF8, "application/json");
var response = await _client.PostAsync("users/"+ upn + "/drive/root:/MailFiles/" + fileName +":/createUploadSession", content);
if (!response.IsSuccessStatusCode)
return null;
var strData = await response.Content.ReadAsStringAsync();
dynamic uploadSession = JsonConvert.DeserializeObject<UploadSessionDTO>(strData);
return uploadSession;
}
public JObject LargeFileUpload(string upn, string url, IFormFile files)
{
var responseCode = HttpStatusCode.OK;
var jObject = new JObject();
int idx = 0;
int fileSize = Convert.ToInt32(files.Length);
int fragSize = 4 * 1024 * 1024; //4MB => 4 * 1024 * 1024;
var byteRemaining = fileSize;
var numFragments = (byteRemaining / fragSize) + 1;
while (idx < numFragments)
{
var chunkSize = fragSize;
var start = idx * fragSize;
var end = idx * fragSize + chunkSize - 1;
var offset = idx * fragSize;
if (byteRemaining < chunkSize)
{
chunkSize = byteRemaining;
end = fileSize - 1;
}
var contentRange = " bytes " + start + "-" + end + "/" + fileSize;
byte[] file = new byte[chunkSize];
using (var client = new HttpClient())
{
var content = new ByteArrayContent(file);
content.Headers.Add("Content-Length", chunkSize.ToString());
content.Headers.Add("Content-Range", contentRange);
var response = client.PutAsync(url, content);
var strData = response.Result.Content.ReadAsStringAsync().Result;
responseCode = response.Result.StatusCode;
//업로드 성공
if (responseCode == HttpStatusCode.Created)
{
JObject data = JObject.Parse(strData);
string downloadUrl = data["#content.downloadUrl"].ToString();
string itemId = data["id"].ToString();
//파일 크기 -> kb로 변환
fileSize = fileSize / 1000;
jObject = JObject.FromObject(new { name = files.Name, id = itemId, url = downloadUrl, size = (double)fileSize });
}
//업로드 충돌
else if (responseCode == HttpStatusCode.Conflict)
{
var restart = RestartByteFile(upn, url, files.Name);
responseCode = restart;
}
}
byteRemaining = byteRemaining - chunkSize;
idx++;
}
if (responseCode == HttpStatusCode.Created) { return jObject; }
else return jObject = JObject.FromObject(new { result = "실패" });
}
When I checked OneDrive, the file was uploaded normally, and when I downloaded and opened the file, it came out as a damaged file.
I wonder why the file gets corrupted when uploaded, and how to fix it.
If the problem cannot be solved, please let us know that it cannot be solved.

Run last Photoshop script (again)

This seems like a trivial issue but I'm not sure Photoshop supports this type of functionality:
Is it possible to implement use last script functionality?
That is without having to add a function on each and every script that writes it's filename to a text file.
Well... It's a bit klunky, but I suppose you could read in the scriptlistener in reverse order and find the first mention of a script file:
// Switch off any dialog boxes
displayDialogs = DialogModes.NO; // OFF
var scripts_folder = "D:\\PS_scripts";
var js = "C:\\Users\\GhoulFool\\Desktop\\ScriptingListenerJS.log";
var jsLog = read_file(js);
var lastScript = process_file(jsLog);
// use function to call scripts
callScript(lastScript)
// Set Display Dialogs back to normal
displayDialogs = DialogModes.ALL; // NORMAL
function callScript (ascript)
{
eval('//#include "' + ascript + '";\r');
}
function process_file(afile)
{
var needle = ".jsx";
var msg = "";
// Let's do this backwards
for (var i = afile.length-1; i>=0; i--)
{
var str = afile[i];
if(str.indexOf(needle) > 0)
{
var regEx = str.replace(/(.+new\sFile\(\s")(.+\.jsx)(.+)/gim, "$2");
if (regEx != null)
{
return regEx;
}
}
}
}
function read_file(inFile)
{
var theFile = new File(inFile);
//read in file
var lines = new Array();
var l = 0;
var txtFile = new File(theFile);
txtFile.open('r');
var str = "";
while(!txtFile.eof)
{
var line = txtFile.readln();
if (line != null && line.length >0)
{
lines[l++] = line;
}
}
txtFile.close();
return lines;
}

Google Script - Attachments to Drive

I have the code below, but i've been struggling to get it to work properly, either it creates duplicate folders every time i run it, or it doesn't upload the attachments and just creates the folders... I am also getting an error now that the newMail Uploads object does not have a .hasnext() function.
What i want to do, is have this script running and it puts attachments in a folder relating to their label -- So in the code below, all mail with the newMail label would go to a single folder, but i want to be able to extend the code further to run for multiple labels ect, so i want to check if the relevant folders exist and if not create them, if they exist they should be used.
-Edit, Now it is only taking the attachment from the first email from a certain address.
function startProcess()
{
var gmailLabels = "newLabel";
var driveFolder = "newFolder";
var archiveLabel = "Processed";
var moveToLabel = GmailApp.getUserLabelByName(archiveLabel);
if ( ! moveToLabel )
{
moveToLabel = GmailApp.createLabel(archiveLabel);
}
findFolder(gmailLabels, driveFolder, archiveLabel, moveToLabel);
}
function findFolder(gmailLabels, driveFolder, archiveLabel, moveToLabel)
{
var filter = "has:attachment label:" + gmailLabels;
var folder = DriveApp.getFoldersByName(driveFolder);
if (folder.hasNext()) {
folder = folder.next();
} else {
folder = DriveApp.createFolder(driveFolder);
}
callThreads(gmailLabels, driveFolder, archiveLabel, moveToLabel, filter, folder)
}
function callThreads(gmailLabels, driveFolder, archiveLabel, moveToLabel, filter, folder)
{
var threads = GmailApp.search(filter);
for (var x=0; x<threads.length; x++) {
var label = GmailApp.getUserLabelByName(gmailLabels);
var message = threads[x].getMessages()[x];
var desc = message.getSubject() + " #" + message.getId();
var att = message.getAttachments();
for (var z=0; z<att.length; z++) {
try {
file = folder.createFile(att[z]);
file.setDescription(desc);
}
catch (e) {
Logger.log(e.toString());
}
}
//threads[x].addLabel(moveToLabel);
label.removeFromThreads(threads);
//threads[x].moveToTrash();
}
}
This is just a suggestion. I haven't tested this code, it probably doesn't work. But that's not the point. I'm trying to show how you might create some order to your code so that it's easier to understand and debug:
function sendToGoogleDrive() {
makeNewFolders();
putEmailsIntoFolders();
};
function makeNewFolders() {
var gmailLabels = "newMail";
var driveFolder = "newMail";
var archiveLabel = "Processed";
var rootUploadFolders ="newMail Uploads";
var rootDriveFolder = DriveApp.getFolders();
var rootExist = false;
var childExist = false;
while (rootDriveFolder.hasNext()) {
var folder = rootDriveFolder.next();
if(folder.getName()==rootUploadFolders) {
var folderId = folder.getId();
if(folder.getName()!==driveFolder) {
var child = DriveApp.getFolderById(folderId).createFolder(driveFolder);
};
};
};
};
function putEmailsIntoFolders() {
};

How to get modified values from dojo table

I have a Dojo table with list of key value pairs. Both fields are editable, once a value is modified i am doing:
var items = grid.selection.getSelected();
However, the modified value is not picked up only the old value is picked.
I tried the following:
dojo.parser.parse()
dojo.parser.instantiate([dojo.byId("tableDiv")]);
but none of them worked. Can any one sugggest a solution for this.
function getAllItems() {
var returnData = "";
//dojo.parser.parse();
//dojo.parser.instantiate([dojo.byId("tableDiv")]);
//grid._refresh();
var items = grid.selection.getSelected();
function gotItems(items, request) {
var i;
for (i = 0; i < items.length; i++) {
var item = items[i];
var paramName = grid.store.getValues(item, "paramName");
var paramValue = grid.store.getValues(item, "paramValue");
if (returnData == "") {
returnData = paramName + "&" + paramValue;
} else {
returnData = returnData + "#" + paramName + "&"
+ paramValue;
} document.getElementById("returnData").value = returnData;
document.getElementById("successFlag").value = "true";
}
}
//Called when loop fails
function fetchFailed(error, request) {
alert("Error reading table data");
}
//Fetch the data.
jsonStore.fetch({
onComplete : gotItems,
onError : fetchFailed
});
}

InDesign copy layer to another document

I am trying to write a script that copies a layer from one document into another.
var srcDocName = 0;
var destDocName = 1;
var layerNameOriginal = "Original";
var layerNameCopyTo = "Destination";
var destDoc = app.documents.item(destDocName);
var layerSrc = app.documents.item(srcDocName).layers.item(layerNameOriginal);
try {
layerSrc.duplicate(destDoc, ElementPlacement.INSIDE);
}
catch(e) {
alert(e)
}
Apparently this works in Photoshop but not in InDesign. I have been trying for ages to find some decent documentation for InDesign scripting. But all I can find is the CS scripting guide, which isn't of much use.
http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/products/indesign/pdfs/InDesignCS5_ScriptingGuide_JS.pdf
If someone can point me to a good reference to the object model I would be grateful.
After some more googling I finally found the answer:
var sourceLayer = app.documents[0].layers.itemByName("Layer1");
var destLayer = app.documents[1].layers[0];
sourceLayer.pageItems.everyItem().duplicate(destLayer);
I also came across jongware which seems to be a complete Object reference extracted directly out of Adobe CS.
You can use this script: https://redokun.com/blog/indesign-copy-entire-layer-one-file-another
The underlying implementation is basically the same, but we've added a UI so it's not necessary to edit the script every time the layer name changes.
Edit: We've been told that the solution above doesn't work with threaded text frames, so I re-wrote the script. The new implementation is way more complex but it now supports threaded TFs.
To expand on the solution offered by Loopo and offer you the ability to copy all layers from 1 document to another...
main();
function main()
{
var source = GetSourceDocument();
if(source == -1)
{
return;
}
var target = GetTargetDocument ();
if(target == -1)
{
return;
}
if(target == source)
{
return;
}
copyLayersOver(source, target);
}
function GetSourceDocument()
{
var returnVal = -1;
var oldPrefs = app.scriptPreferences.userInteractionLevel;
app.scriptPreferences.userInteractionLevel=UserInteractionLevels.INTERACT_WITH_ALL;
var dialog = app.dialogs.add({name:"Document to Copy From", canCanel: true, label:"DocumentToCopyFrom"});
var col1 = dialog.dialogColumns.add();
var StringList= [];
for(var i = 0; i<app.documents.length; i++)
{
StringList.push("[" + app.documents[i].index + "] " + app.documents[i].name);
}
var ddl = col1.dropdowns.add({id:"SourceDocDDL", stringList: StringList});
if(dialog.show() == true)
{
returnVal = ddl.stringList[ddl.selectedIndex].split("]")[0].substr(1);
}
else
{
returnVal -1;
}
dialog.destroy();
app.scriptPreferences.userInteractionLevel = oldPrefs;
return returnVal;
}
function GetTargetDocument()
{
var returnVal = -1;
var oldPrefs = app.scriptPreferences.userInteractionLevel;
app.scriptPreferences.userInteractionLevel=UserInteractionLevels.INTERACT_WITH_ALL;
var dialog = app.dialogs.add({name:"Document to Copy To", canCanel: true, label:"DocumentToCopyTo"});
var col1 = dialog.dialogColumns.add();
var StringList= [];
for(var i = 0; i<app.documents.length; i++)
{
StringList.push("[" + app.documents[i].index + "] " + app.documents[i].name);
}
var ddl = col1.dropdowns.add({id:"SourceDocDDL", stringList: StringList});
if(dialog.show() == true)
{
returnVal = ddl.stringList[ddl.selectedIndex].split("]")[0].substr(1);
}
else
{
returnVal -1;
}
dialog.destroy();
app.scriptPreferences.userInteractionLevel = oldPrefs;
return returnVal;
}
function copyLayersOver(source, target)
{
var sourceDocument = app.documents[source];
var targetDocument = app.documents[target];
var sourceLayers = sourceDocument.layers;
//Match the number of pages
while(targetDocument.pages.length < sourceDocument.pages.length)
{
targetDocument.pages.add();
}
//copy the layers over
for(var i= 0; i < sourceLayers.length; i++)
{
var names = targetDocument.layers.everyItem().name;
var merge = false;
for(var y = 0; y < names.length; y++)
{
if(names[y] == sourceLayers[i].name)
{
merge = true;
break;
}
}
if(merge)
{
var targetLayer = targetDocument.layers.add();
targetLayer.name = "temp";
sourceLayers[i].pageItems.everyItem().duplicate(targetLayer);
targetDocument.layers.itemByName(sourceLayers[i].name).merge(targetLayer);
}
else
{
var targetLayer = targetDocument.layers.add();
targetLayer.name = sourceLayers[i].name;
targetLayer.layerColor = sourceLayers[i].layerColor;
sourceLayers[i].pageItems.everyItem().duplicate(targetLayer);
}
}
}