Solve the problem that the Onlyoffice file version changes and the problem that multiple people cannot edit collaboratively after using dynamic keys

1.Cause analysis

Onlyoffice’s file saving mechanism relies on the callback interface to save files. Once the file is saved successfully. When the editor is opened again with the last key and the latest document URL address as parameters, the editor service goes to redis to find the cache based on the key and verifies whether the version of the file has changed. If it is the same, it reads it from the cache. Document data. Otherwise, a prompt will appear indicating that the file version has changed.

2. Solution

Once you know the verification mechanism of the Onlyoffice editor, you can solve the problem.

We can create a table to manage file version numbers. The rules for creating version numbers are determined by yourself.

Idea:

Every time the editor calls back, we will check whether the file exists in the file version table. If it does not exist, create a record. If it exists, the version number will be increased by 1.

Add another interface to obtain the editor KEY. The interface logic is to find whether there is corresponding document data in the table. If so, add 1 to the original version number. If it does not start with 1.

In this case, the prompts that can solve the file version problem can also solve the problem that documents cannot be coordinated after dynamic KEY.

3. Code

OnlyOfficeFile table name, the table structure is as follows:

Here I want to explain the composition of my key here: type_id_VersionNo example FlowTask_00018de2895742fb8edba512db6f619c_1

Callback interface code:

/// <summary>
    /// Summary description of callback interface CallbackApiHandler
    /// </summary>
    public class CallbackApiHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            //context.Response.AddHeader("Access-Control-Allow-Origin", "*");
            //context.Response.AddHeader("Access-Control-Allow-Headers", " x-www-form-urlencoded, Content-Type,x-requested-with");
            //context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
            string errorMsg = string.Empty;
            string body = string.Empty;
            var fileDataJson = string.Empty;
            bool isSucceed = false;
            string search1 = string.Empty;
            string search2 = string.Empty;
            string status = string.Empty;
            var ip = CommonHelpLD.ServiceIp;
            var model = new OnlyOfficeFileModel();
            try
            {
                body = HttpContextHelper.GetRequestBody(context);
                var result1 = new LawcaseTaskService().AddLog(string.Empty, string.Empty, "CallbackApi", body, string.Empty, string.Empty, "Callback Interface 1", ip);
                //LogHelper.WriteLog("Callback interface 1 starts CallbackApiHandler. Whether it is successful:" + isSucceed + "Interface information:" + errorMsg + ", received request parameters" + body + ",fileDataJson:\ " + fileDataJson);
                if (!string.IsNullOrEmpty(body))
                {
                    var endIndex = body.IndexOf("fileDataJson");//, fileDataJson:
                    if (endIndex > 0)
                    {
                        body = body.Substring(0, endIndex - 15);
                        body = body.Trim().TrimEnd(',');
                        var result2 = new LawcaseTaskService().AddLog(string.Empty, string.Empty, "CallbackApi", body, string.Empty, string.Empty, "Callback Interface 2", ip);
                        //LogHelper.WriteLog("Callback interface 2 starts CallbackApiHandler whether it is successful:" + isSucceed + "Interface information:" + errorMsg + ", received request parameters" + body + ",fileDataJson:\ " + fileDataJson);
                    }
                    var fileData = new JavaScriptSerializer().Deserialize<CallbackApiReqModel>(body);
                    //var fileData = JsonConvert.DeserializeObject<CallbackApiReqModel>(body);
                    errorMsg = "try 0";

                    if (fileData != null & amp; & amp; (fileData.status == 2 || fileData.status == 6))
                    {
                        status = fileData.status.ToString();
                        try
                        {
                            errorMsg + = "try 1";
                            //fileData.Id = fileData.key.Contains("_") ? fileData.key.Substring(0, fileData.key.IndexOf("_")) : fileData.key;
                            if (fileData.key.Contains("_"))
                            {
                                var keys = fileData.key.Split('_');
                                if (keys.Length >= 3)
                                {
                                    fileData.Id = string.Format("{0}_{1}", keys[0], keys[1]);
                                }
                                else
                                {
                                    fileData.Id = keys[1];//FlowTask_8160b1f7efa64cdba7d4bd37e843d638
                                }
                            }
                            else
                            {
                                fileData.Id = fileData.key;
                            }
                            errorMsg + = "try 2," + fileData.key;
                            var fileModel = FileHelper.GetFileObjModel(fileData.key);//(fileData.Id);
                            var sFilePath = FileHelper.GetFilePath(fileModel.FileType);
                            string sFileName = string.Format("{0}.docx", fileModel.Key);
                            var PATH_FOR_SAVE = sFilePath + "/" + sFileName; //The absolute path of the file
                            //if (File.Exists(PATH_FOR_SAVE))
                            //{
                            // File.Delete(PATH_FOR_SAVE);
                            // errorMsg + = "try 1.1";
                            //}
                            search1 = fileModel.Key;
                            search2 = fileData.key;
                            model.FileKey = fileData.key;
                            model.Type = fileModel.FileType;
                            model.Name = sFileName;
                            model.DisplayName = sFileName;
                            model.TaskId = search1;
                            model.CreatedBy = "CallbackApi";
                            model.VersionNo = 1;
                            var model_o = OnlyOfficeFileService.GetModelByTaskId(model.TaskId, model.Type);
                            if (model_o != null)
                            {
                                model.VersionNo = model_o.VersionNo + 1;
                            }
                            var result3 = new LawcaseTaskService().AddLog(search1, search2, "CallbackApi", body, PATH_FOR_SAVE, "status:" + status, "Callback Interface 3", ip);
                            var req = WebRequest.Create(fileData.url);
                            errorMsg + = "try 2.1,PATH_FOR_SAVE:" + PATH_FOR_SAVE;

                            using (var stream = req.GetResponse().GetResponseStream())
                            {
                                errorMsg + = "try 3";
                                using (var fs = File.Open(PATH_FOR_SAVE, FileMode.Create))
                                {
                                    var buffer = new byte[4096];
                                    int read;
                                    errorMsg + = "try 4";
                                    while ((readed = stream.Read(buffer, 0, 4096)) != 0)
                                    {
                                        fs.Write(buffer, 0, read);
                                        //errorMsg = "try 5";
                                    }
                                }
                            }
                            isSucceed = true;
                            model.FilePath = PATH_FOR_SAVE.Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
                            errorMsg + = "try 6";
                            try
                            {
                                if (fileModel.FileType.Equals("FlowTask"))
                                {
                                    var result = new LawcaseTaskService().UpdateTaskStatus(fileModel.Key, 1);
                                    errorMsg + = " try 7 Update task Modify the document task to in progress...1, update result: " + result.Item1 + ", message: " + result.Item2;
                                }
                            }
                            catch (Exception ex)
                            {
                                errorMsg + = " try 7 Update task Modify the document task to be in progress... 1 Exception:" + ex.Message;
                            }
                            errorMsg + = " try 8";
                        }
                        catch (Exception ex)
                        {
                            isSucceed = false;
                            errorMsg + = "Exception 2:" + ex.Message;
                        }
                    }
                    else
                    {
                        errorMsg + = "try 66";
                        isSucceed = true;
                    }
                    fileDataJson = JsonConvert.SerializeObject(fileData);
                }
                else
                {
                    isSucceed = true;
                }
            }
            catch (Exception ex)
            {
                isSucceed = false;
                errorMsg + = "Exception 1:" + ex.Message;
            }
            var rspJosn = "{"error":0}";//return save successfully
            if(isSucceed)
            {
                OnlyOfficeFileService.SaveModel(model);
            }
            else
            {
                rspJosn = "{"error":1}";//return failed to save
            }
            //LogHelper.WriteLog("Callback interface 4 ends CallbackApiHandler. Whether it is successful:" + isSucceed + "Interface information:" + errorMsg + ", received request parameters" + body + ",fileDataJson:\ " + fileDataJson);
            var result4 = new LawcaseTaskService().AddLog(search1, search2, "CallbackApi", body, rspJosn, "status:" + status, "Callback interface 4," + errorMsg, ip);
            context.Response.Write(rspJosn);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

In the above code, we mainly look at these sentences. After you find it, use the context to understand it.

model.FileKey = fileData.key;
                            model.Type = fileModel.FileType;
                            model.Name = sFileName;
                            model.DisplayName = sFileName;
                            model.TaskId = search1;
                            model.CreatedBy = "CallbackApi";
                            model.VersionNo = 1;
                            var model_o = OnlyOfficeFileService.GetModelByTaskId(model.TaskId, model.Type);
                            if (model_o != null)
                            {
                                model.VersionNo = model_o.VersionNo + 1;
                            }
var result = new LawcaseTaskService().UpdateTaskStatus(fileModel.Key, 1);

This problem has been solved in actual projects.